/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.mrql;

import org.apache.mrql.gen.*;
import java.io.*;
import javax.swing.*;
import javax.swing.JTree.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;


/* The MRQL debugger that uses the lineage generated in Provenance.gen */
public class Debugger extends JPanel implements TreeSelectionListener {
    final MRData result;
    final JTree tree;
    final JTextField search = new JTextField(20);
    static JFrame frame;
    private static volatile boolean exit = false;
    private static volatile boolean trace_nodes_only = false;
    Trees exprs;

    /** wrapped strings to be colored red */
    private final static class TaggedString {
        public String value;
        TaggedString ( String value ) { this.value = value; }
        public String toString () { return value; }
    }

    public Debugger ( MRData result_value, Trees exprs ) {
        super(new GridLayout(1,0));
        result = result_value;
        this.exprs = exprs;
        JToolBar toolBar = new JToolBar("");
        toolBar.setPreferredSize(new Dimension(1000,40));
        JButton button = new JButton();
        button.setActionCommand("Exit");
        button.setText("exit");
        final JFrame nframe = frame;
        button.addActionListener(new ActionListener() {
                public void actionPerformed ( ActionEvent e ) {
                    nframe.setVisible(false);
                    nframe.dispose();
                    exit = true;
                }
            });
        button.setVisible(true);
        toolBar.add(button);
        toolBar.add(Box.createRigidArea(new Dimension(200,0)));
        JCheckBox checkb = new JCheckBox();
        checkb.setActionCommand("traceOnly");
        checkb.setText("trace nodes only");
        checkb.addActionListener(new ActionListener() {
                public void actionPerformed ( ActionEvent e ) {
                    trace_nodes_only = !trace_nodes_only;
                    if (trace_nodes_only) {
                        search.setText("");
                        DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
                        DefaultMutableTreeNode root = createNode(result,"","");
                        root.setUserObject("results with trace and input nodes only");
                        model.setRoot(root);
                        model.reload(root);
                    } else reset();
                }
            });
        checkb.setVisible(true);
        toolBar.add(checkb);
        button = new JButton();
        button.setActionCommand("Previous");
        button.setText("prev");
        button.addActionListener(new ActionListener() {
                public void actionPerformed ( ActionEvent e ) {
                }
            });
        button.setVisible(false);
        //toolBar.add(button);
        button = new JButton();
        button.setActionCommand("Next");
        button.setText("next");
        button.addActionListener(new ActionListener() {
                public void actionPerformed ( ActionEvent e ) {
                }
            });
        button.setVisible(false);
        //toolBar.add(button);
        toolBar.add(Box.createRigidArea(new Dimension(200,0)));
        button = new JButton();
        button.setActionCommand("Clear");
        button.setText("clear");
        button.addActionListener(new ActionListener() {
                public void actionPerformed ( ActionEvent e ) {
                    reset();
                }
            });
        toolBar.add(button);
        toolBar.add(search);
        button = new JButton();
        button.setActionCommand("SearchOutput");
        button.setText("Search Output");
        button.addActionListener(new ActionListener() {
                public void actionPerformed ( ActionEvent e ) {
                    if (!search.getText().equals("")) {
                        DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
                        DefaultMutableTreeNode root = createNode(result,search.getText(),"");
                        root.setUserObject("search output results");
                        model.setRoot(root);
                        model.reload(root);
                    }
                }
            });
        toolBar.add(button);
        button = new JButton();
        button.setActionCommand("SearchInput");
        button.setText("Search Input");
        button.addActionListener(new ActionListener() {
                public void actionPerformed ( ActionEvent e ) {
                    if (!search.getText().equals("")) {
                        DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
                        DefaultMutableTreeNode root = createNode(result,"",search.getText());
                        root.setUserObject("search input results");
                        model.setRoot(root);
                        model.reload(root);
                    }
                }
            });
        toolBar.add(button);
        tree = new JTree(createNode(result,"",""));
        JScrollPane sp = new JScrollPane(tree,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                                         JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        sp.setPreferredSize(new Dimension(1000,2000));
        sp.getVerticalScrollBar().setPreferredSize(new Dimension(20,0));
        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        Font currentFont = tree.getFont();
        tree.setFont(new Font(currentFont.getName(),
                              currentFont.getStyle(),
                              (int)(currentFont.getSize()*1.5)));
        DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() {
                public Component getTreeCellRendererComponent
                    ( JTree tree, Object value, boolean sel, boolean exp,
                      boolean leaf, int row, boolean hasFocus ) {
                    super.getTreeCellRendererComponent(tree,value,sel,exp,leaf,row,hasFocus);
                    // tagged strings are red
                    if (((DefaultMutableTreeNode)value).getUserObject() instanceof TaggedString)
                        setForeground(Color.red);
                    return this;
                }
            };
        renderer.setLeafIcon(null);
        renderer.setOpenIcon(null);
        renderer.setClosedIcon(null);
        tree.setCellRenderer(renderer);
        tree.addTreeSelectionListener(this);
        setLayout(new BorderLayout());
        add(toolBar,BorderLayout.NORTH);
        add(sp,BorderLayout.CENTER);
    }

    public void valueChanged ( TreeSelectionEvent e ) { }

    private void reset () {
        search.setText("");
        DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
        DefaultMutableTreeNode root = createNode(result,"","");
        root.setUserObject("results");
        model.setRoot(root);
        model.reload(root);
    }

    private String exprNode ( Tree e ) {
        match e {
        case call(source,_,`path,...):
            return path.stringValue();
        case trace(`msg,_,_):
            return msg.stringValue();
        case call(`f,...):
            return f.toString();
        case cmap(lambda(`v,_),_):
            return "cmap "+v;
        case groupBy(_):
            return "groupBy";
        case coGroup(...):
            return "coGroup";
        case reduce(`m,...):
            return "reduce("+m+")";
        case project(`v,`a):
            return exprNode(v)+"."+a;
        case nth(`x,`n):
            return exprNode(x)+"#"+n;
        case `f(...):
            return f;
        };
        return e.toString();
    }

    private boolean consider_node ( Tree e ) {
        match e {
        case call(source,...): return true;
        case trace(...): return true;
        };
        return !trace_nodes_only;
    }

    private boolean existing_child ( DefaultMutableTreeNode node, DefaultMutableTreeNode parent ) {
        Object no = node.getUserObject();
        String ns = (no instanceof TaggedString) ? ((TaggedString)no).value : (String)no;
        for ( int i = 0; i < parent.getChildCount(); i++ ) {
            Object co = ((DefaultMutableTreeNode)parent.getChildAt(i)).getUserObject();
            String cs = (co instanceof TaggedString) ? ((TaggedString)co).value : (String)co;
            if (cs.equals(ns))
                return true;
        };
        return false;
    }

    private void create_nodes ( MRData value, DefaultMutableTreeNode parent,
                                String inputSearch, boolean first ) {
        Tuple p = ((Tuple)value);
        MRData v = p.get(1);
        Tree opr = exprs.nth(((MR_int)p.get(0)).get());
        Tree tp = exprs.nth(((MR_int)p.get(0)).get()-1);
        match tp {
        case `T(`etp):
            if (!Provenance.is_collection(T))
                fail;
            tp = etp;
        }
        DefaultMutableTreeNode node
            = new DefaultMutableTreeNode((first) ? Printer.print(v,tp)
                                         : exprNode(opr)+": "+Printer.print(v,tp));
        if (first || consider_node(opr)) {
            if (!existing_child(node,parent))
                parent.add(node);
        } else node = parent;
        for ( int i = 2; i < p.size(); i++ )
            if (p.get(i) instanceof Bag)
                for ( MRData e: (Bag)p.get(i) )
                    create_nodes(e,node,inputSearch,false);
            else create_nodes(p.get(i),node,inputSearch,false);
        boolean matched = false;
        for ( int i = 0; i < node.getChildCount(); i++ ) {
            DefaultMutableTreeNode child = (DefaultMutableTreeNode)node.getChildAt(i);
            matched |= child.getUserObject() instanceof TaggedString;
        };
        if (matched && node.getUserObject() instanceof String)
            node.setUserObject(new TaggedString((String)node.getUserObject()));
        else match opr {
        case call(source,...):
            if (!inputSearch.equals("") && v.toString().contains(inputSearch)
                && node.getUserObject() instanceof String)
                node.setUserObject(new TaggedString((String)node.getUserObject()));
        }
    }

    private DefaultMutableTreeNode createNode ( MRData value, String outputSearch, String inputSearch ) {
        if (value instanceof Bag) {
            DefaultMutableTreeNode node = new DefaultMutableTreeNode("results");
            for ( MRData e: (Bag)value )
                if (outputSearch.equals("") || ((Tuple)e).get(0).toString().contains(outputSearch))
                    create_nodes(((Tuple)e).get(1),node,inputSearch,true);
            return node;
        } else if (value instanceof MR_dataset) {
            DefaultMutableTreeNode node = new DefaultMutableTreeNode("results");
            for ( MRData e: ((MR_dataset)value).dataset().take(Config.max_bag_size_print) )
                if (outputSearch.equals("") || ((Tuple)e).get(0).toString().contains(outputSearch))
                    create_nodes(((Tuple)e).get(1),node,inputSearch,true);
            return node;
        } else {
            DefaultMutableTreeNode node = new DefaultMutableTreeNode("value");
            if (outputSearch.equals("") || ((Tuple)value).get(0).toString().contains(outputSearch))
                create_nodes(((Tuple)value).get(1),node,inputSearch,true);
            return node;
        }
    }

    private static void createAndShowGUI ( MRData lineage, Tree tp, Trees exprs ) {
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
 	frame.addWindowListener(new WindowListener() {
                public void windowClosing ( WindowEvent e ) {
                    frame.setVisible(false);
                    frame.dispose();
                    exit = true;
                }
                public void windowActivated ( WindowEvent e ) {}
                public void windowClosed ( WindowEvent e ) {}
                public void windowDeactivated ( WindowEvent e ) {}
                public void windowDeiconified ( WindowEvent e ) {}
                public void windowIconified ( WindowEvent e ) {}
                public void windowOpened ( WindowEvent e ) {}
            });
        frame.add(new Debugger(lineage,exprs));
        frame.pack();
        frame.setVisible(true);
    }

    /** use the MRQL debugger on a query result
     * @param lineage the query result extended with lineage
     * @param type the result type
     * @param exprs the expr terms used in the lineage
     */
    public static void debug ( final MRData lineage, final Tree type, final Trees exprs ) {
        try {
            exit = false;
            trace_nodes_only = false;
            frame = new JFrame("MRQL debugger");
            SwingUtilities.invokeLater(new Runnable() {
                    public void run () {
                        createAndShowGUI(lineage,type,exprs);
                    }
                });
            while (!exit)
                Thread.sleep(1000);
        } catch (Exception ex) {
        }
    }
}
