package com.maplesoft.maplenet.demo;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.applet.*;
import java.net.URL;
import javax.swing.*;
import java.util.Vector;
import com.maplesoft.client.*;


public class SolveEquations extends Applet {


  // local variables
  boolean isStandalone = false;
  String host;
  int port;
  String user;
  String password;

  JLabel title = new JLabel("Please Enter the Equation(s) or Inequation(s) below",JLabel.CENTER);
  JPanel eqnPanel = new JPanel();
  JPanel varPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
  JPanel buttonPanel = new JPanel(new FlowLayout());
  JPanel solPanel = new JPanel();
  JLabel varLabel = new JLabel("variáveis: ",JLabel.LEFT);
  Vector tfs = new Vector(3);
  JTextField varTF = new JTextField(20);
  JButton solve = new JButton("resolva");
  JButton evalf = new JButton("resolva numericamente");
  JButton add = new JButton("adicione");
  JButton remove = new JButton("remova");
  JButton clear = new JButton("limpa");
  mathmlEquation sol = new mathmlEquation();


  public SolveEquations() {} // constructor


  public void init() {
    try {
      URL url=getDocumentBase();
      String sDocHost=url.getHost();
      host=this.getParameter("host",sDocHost);
    } catch (Exception e){e.printStackTrace();}
    try {
      port = Integer.parseInt(this.getParameter("port","14444"));
    } catch(Exception e){e.printStackTrace();}
    try {
      user=this.getParameter("usuário","teste");
    } catch(Exception e){e.printStackTrace();}
    try {
      password=this.getParameter("senha","teste");
    } catch(Exception e){e.printStackTrace();}
    try {jbInit();} catch(Exception e) {e.printStackTrace();}
  } // end init()

  public void start() {} // end start()
  public void stop() {} // end stop()
  public void destroy() {} // end destroy()


  private void jbInit() throws Exception {
    iniTfs();
    setEqnPanel(); setVarPanel(); setButtonPanel(); setSolPanel();
    eqnPanel.setBackground(SystemColor.info);
    varPanel.setBackground(SystemColor.info);
    buttonPanel.setBackground(SystemColor.info);
    solPanel.setBackground(SystemColor.info);
    solPanel.setMinimumSize(new Dimension(376,200));
    solPanel.setPreferredSize(new Dimension(376,200));
    this.setSize(400,500);
    this.setLayout(new GridBagLayout());
    this.setBackground(SystemColor.info);
    GridBagAdder.add(this, title, 0, 0, 1, 1, 1, 0, GridBagConstraints.NONE, GridBagConstraints.CENTER);
    GridBagAdder.add(this, eqnPanel, 0, 1, 1, 1, 1, 0, GridBagConstraints.NONE, GridBagConstraints.CENTER);
    GridBagAdder.add(this, varPanel, 0, 2, 1, 1, 1, 0, GridBagConstraints.VERTICAL, GridBagConstraints.CENTER);
    GridBagAdder.add(this, buttonPanel, 0, 3, 1, 1, 1, 0, GridBagConstraints.NONE, GridBagConstraints.CENTER);
    GridBagAdder.add(this, solPanel, 0, 4, 1, 1, 1, 0, GridBagConstraints.NONE, GridBagConstraints.CENTER);
  } // end ibInit

  private void iniTfs() {
    for (int i=0; i<tfs.capacity(); i++) {
      boolean aBoolean = tfs.add(new JTextField(34));
    } // end for
  } // end iniTfs()

  private void setEqnPanel() {
    eqnPanel.removeAll();
    eqnPanel.setLayout(new GridLayout(tfs.size(),1));
    for (int i=0; i<tfs.size(); i++) {
      eqnPanel.add((JTextField)tfs.get(i));
    } // end for
  } // end setEqnPanel()

  private void setVarPanel() {
    varPanel.add(varLabel);
    varPanel.add(varTF);
  } // end setVarPanel()

  private void setButtonPanel() {
    solve.addActionListener(new SolveButtonListener());
    evalf.addActionListener(new EvalfButtonListener());
    add.addActionListener(new AddButtonListener());
    remove.addActionListener(new RemoveButtonListener());
    clear.addActionListener(new ClearButtonListener());
    solve.setToolTipText("resolva algebricamente");
    evalf.setToolTipText("resolva numéricamente");
    add.setToolTipText("adicione um TextField");
    remove.setToolTipText("remova um TextField");
    clear.setToolTipText("limpe tudo");
    buttonPanel.add(solve);
    buttonPanel.add(evalf);
    buttonPanel.add(add);
    buttonPanel.add(remove);
    buttonPanel.add(clear);
  } // end setButtonPanel()

  private void setSolPanel() {
      solPanel.setLayout(null);
      sol.setBackground(SystemColor.info);
      sol.setBounds(new Rectangle(0,0,376,200));
      sol.initBG(SystemColor.info);
      sol.setControls( true );
      sol.registerControls( true );
      sol.setLinebreak( true );
      sol.allow_cut = true;
      sol.setVAlign("top");
      sol.setDrawBorder( true );
      solPanel.add(sol);
  } // end setSolPanel()


  private String[] getSolveStatement() {
    String ms = "[solve("+getEqnsVars()+")]";
    return withProc(ms);
  } // end getSolveStatement()

  private String[] getEvalfStatement() {
    String me = "[evalf(solve("+getEqnsVars()+"))]";
    return withProc(me);
  } // end getEvalfStatement()

  private String getEqnsVars() {
    String ev = "{";
    boolean eqnExistence = false;
    for (int i=0; i<tfs.size(); i++) {
      String anEqn = ((JTextField)tfs.get(i)).getText();
      if (isValidEqn(anEqn)) {eqnExistence=true; ev+=anEqn; ev+=",";}
    } // end for
    if (eqnExistence) {
      ev=ev.trim();
      ev=ev.substring(0,ev.length()-1);
      ev += "},{" + varTF.getText() + "}";
    } else {ev = "{},{}";}
    return ev;
  } // end getEqnsVars

  private String[] withProc(String solveOnly) {
    String[] mp = new String[3];
    mp[0] = "sol:="+solveOnly+":";
    mp[1] = "exportSol:=proc(solutions) ";
    mp[1] += "local solString, oneSol, n, i: ";
    mp[1] += "use MathML in ";
    mp[1] += "n := nops(solutions): ";
    mp[1] += "solString := \"<math><mrow><mtable>\": ";
    mp[1] += "for i from 1 to (n-1) do ";
    mp[1] += "oneSol:=substring(ExportPresentation(solutions[i]),50..-8): ";
    mp[1] += "solString := cat(solString, \"<mtr><mtd>\", oneSol, \"</mtd></mtr>\"): ";
    mp[1] += "end do: ";
    mp[1] += "solString := cat(solString,substring(ExportPresentation(solutions[n]),50..-8)): ";
    mp[1] += "solString := cat(solString,\"</mtable></mrow></math>\"): ";
    mp[1] += "end use: solString: end proc: ";
    mp[2] = "exportSol(sol);";
    return mp;
  } // end withProc()

  private boolean isValidEqn(String eqn) {
    if (eqn.trim().length()>0) {return true;} return false;
  } // end isValidEqn()


  private void solveEqns() {
    mapleExecute(getSolveStatement());
  } // end solveEqns()

  private void evalfEqns() {
    mapleExecute(getEvalfStatement());
  } // end evalfEqns()

  private void mapleExecute(String[] mapleIn) {
    System.out.println("conecte: "+host+":"+port);
    System.out.println("Nome do usuário: "+user);
    System.out.println("senha: "+password);
    MapleStatement maple = new MapleStatement(host,port,user,password);
    System.out.println("Entrada da Maple Engine : "+mapleIn[0]+" "+mapleIn[2]);
    try {
      String[] mapleOut = maple.execute(mapleIn);
      System.out.println("Saída da Maple Engine: "+mapleOut[0]+" "+mapleOut[2]);
      sol.setEquation(mapleOut[2]);
    } catch (Exception ex) {System.out.println("maple computation error"+ex.toString());
    } //
    // sol.repaint();
  } // end mapleExecute()

  private String ignoreProc(String multiLines) {
    if (multiLines!=null) {
      String endproc = "fim de processo";
      String mathml;
      int m = multiLines.indexOf(endproc);
      mathml = multiLines.substring(m+endproc.length());
      mathml = mathml.trim();
      if (mathml.startsWith("\"<math>")&&mathml.endsWith("</math>\"")) {
        return mathml.substring(mathml.indexOf("\"")+1,mathml.lastIndexOf("\""));
      } else {return "<math><mtext>either invalid input, or unable to return all symbolic solution, please try numerically solve</mtext></math>";}
    } // end if
    else {return "<math><mtext>either invalid input or no solution</mtext></math>";}
  } // end ignoreProc()


  public String getAppletInfo() {
    return "Informação do Applet: resolvendo um sistema de equação(s) ou inequação(s)";
  } // end getAppletInfo()

  public String getParameter(String key, String def) {
    return isStandalone ? System.getProperty(key, def) :
      (getParameter(key) != null ? getParameter(key) : def);
  } // end getParameter()

  public String[][] getParameterInfo() {
    return null;
  } // end getParameterInfo()


  public void addEqn() {
    if (tfs.size()<10) {
      if (tfs.add(new JTextField(34))) {this.setEqnPanel();}
      this.validate();
    } // end if (max 10 equations could be input)
  } // end addEqn()

  public void removeEqn() {
    for (int i=tfs.size()-1; i>=0; i--) {
      if (!isValidEqn(((JTextField)tfs.get(i)).getText())&&tfs.size()>1) {
        tfs.remove(i); this.setEqnPanel(); this.validate(); return;
      } // end if
    } // end for
    if (tfs.size()>1) {tfs.remove(tfs.size()-1); this.setEqnPanel(); this.validate();}
  } // removeEqn()


  public static void main(String[] args) {
    SolveEquations applet = new SolveEquations();
    applet.isStandalone = true;
    Frame frame;
    frame = new Frame();
    frame.setTitle("Applet Frame");
    frame.add(applet, BorderLayout.CENTER);
    applet.init();
    applet.start();
    frame.setSize(600,500);
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    frame.setLocation((d.width - frame.getSize().width) / 2, (d.height - frame.getSize().height) / 2);
    frame.setVisible(true);
  } // end main


  static class GridBagAdder {
    static GridBagConstraints cons = new GridBagConstraints();
      public static void add(Container cont, Component comp, int x, int y,
        int width, int height, int weightx, int weighty, int fill, int anchor) {
        cons.gridx=x; cons.gridy=y;
        cons.gridwidth=width; cons.gridheight=height;
        cons.weightx=weightx; cons.weighty=weighty;
        cons.fill=fill; cons.anchor=anchor;
        cont.add(comp,cons);
   } // end add()
  } // end static inner class GridBagAdder

  public class SolveButtonListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      solveEqns();
    } // end actionPerformed
  } // end SolveButtonListener()

  public class EvalfButtonListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      evalfEqns();
    } // end actionPerformed()
  } // end SolveButtonListener

  public class AddButtonListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
       addEqn();
     } // end actionPerformed()
  } // end AddButtonListener

  public class RemoveButtonListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
       removeEqn();
     } // end actionPerformed()
  } // end RemoveButtonListener

  public class ClearButtonListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      for (int i=0; i<tfs.size(); i++) {
        ((JTextField)tfs.get(i)).setText("");
      } // end for
      varTF.setText("");
      sol.setEquation("");
    } // end actionPerformed()
  } // end ResetButtonListener


} // end SolveEquations
