/*
 * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved.
 */
package ch.psi.plot.jlchart;

import ch.psi.plot.LinePlotBase;
import ch.psi.plot.LinePlotSeries;
import ch.psi.plot.utils.SwingUtils;
import fr.esrf.tangoatk.widget.util.chart.DataList;
import fr.esrf.tangoatk.widget.util.chart.JLAxis;
import fr.esrf.tangoatk.widget.util.chart.JLChart;
import fr.esrf.tangoatk.widget.util.chart.JLDataView;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

/**
 *
 */
public class LinePlot extends LinePlotBase {

    JLChart plot;

    final ArrayList<JLDataView> views = new ArrayList<>();

    public LinePlot() {
        super();
        setRequireUpdateOnAppend(false);
    }
    
    
    static final Color[] defaultColors = new Color[]{Color.RED,Color.BLUE,Color.GREEN,Color.ORANGE,Color.MAGENTA,Color.CYAN,Color.YELLOW,Color.PINK,Color.LIGHT_GRAY,Color.GRAY};
    Random random;

    int colorIndex=0;
    @Override
    protected Object onAddedSeries(LinePlotSeries series) {
        JLDataView view = new JLDataView();
        Color color = series.getColor();
        if (color==null){
            if (colorIndex < defaultColors.length) {
                color = defaultColors[colorIndex%10];
                colorIndex++;
            }
            if (color==null){
                if (random==null)
                    random = new Random(1000);// Generate a random color, but repeatable for same graphs.
                color = SwingUtils.generateRandomColor(random);            
            }
        }
        view.setColor(color);        
        //view.setLineWidth(1);

        int markerSize = 4;
        view.setName(series.getName());
        view.setMarkerSize(markerSize);
        view.setMarkerColor(color);

        view.setViewType(JLDataView.TYPE_LINE);

        if (markerSize > 0) {
            view.setMarker(JLDataView.MARKER_DOT);
        } else {
            view.setMarker(JLDataView.MARKER_NONE);
        }

        if (series.getAxisY() == 2) {
            plot.getY2Axis().addDataView(view);
        } else {
            plot.getY1Axis().addDataView(view);
        }
        return view;
    }

    JLDataView getDataView(LinePlotSeries series) {
        return (JLDataView) (series.getToken());
    }

    @Override
    protected void onRemovedSeries(LinePlotSeries series) {
        JLDataView view = getDataView(series);
        for (int i = 0; i < plot.getY1Axis().getViewNumber(); i++) {
            if (view.getName().equals(plot.getY1Axis().getDataView(i).getName())) {
                plot.getY1Axis().removeDataView(view);
            }

        }
        for (int i = 0; i < plot.getY2Axis().getViewNumber(); i++) {
            if (view.getName().equals(plot.getY2Axis().getDataView(i).getName())) {
                plot.getY2Axis().removeDataView(view);
            }
        }
    }

    @Override
    protected void onAppendData(LinePlotSeries series, double x, double y) {
        JLDataView view = getDataView(series);
        if (view != null) 
        {
            if (isUpdatesEnabled())
                plot.addData(view, x, y);
            else
                view.add(x, y);            
            if (series.getMaxItemCount()>0){    
                view.garbagePointLimit(series.getMaxItemCount());        
           }
        }
    }

    @Override
    protected void onSetData(LinePlotSeries series, double[] x, double[] y) {
        JLDataView view = getDataView(series);
        if (view != null) {
            view.setData(x, y);
            if (series.getMaxItemCount()>0){    
                view.garbagePointLimit(series.getMaxItemCount());        
           }
        }
    }

    @Override
    public double[][] getSeriesData(LinePlotSeries series) {
        JLDataView view = getDataView(series);
        double[] x = new double[view.getDataLength()];
        double[] y = new double[x.length];
        int index = 0;
        DataList data = view.getData();
        while (data != null) {
            if (index >= x.length) {
                break;
            }
            x[index] = data.x;
            y[index] = data.y;
            index++;
            data = data.next;
        }
        return new double[][]{x, y};
    }

    @Override
    protected void onShown() {
        addKeyBindings();
    }
    
    @Override
    protected void createChart() {
        super.createChart();
        
        plot = new JLChart();
        plot.getXAxis().setAnnotation(JLAxis.VALUE_ANNO);
        //plot.getXAxis().setLabelFormat(JLAxis.SCIENTIFIC_FORMAT);
        plot.getY1Axis().setAutoScale(true);
        plot.getY2Axis().setAutoScale(true);
        plot.getXAxis().setAutoScale(true);
        plot.getY1Axis().setGridVisible(true);
        plot.getXAxis().setGridVisible(true);

        /*
         plot.getY1Axis().setAutoScale(false);
         plot.getY2Axis().setAutoScale(false);
         plot.getXAxis().setAutoScale(false);        
         plot.getY1Axis().setMinimum(0);
         plot.getY1Axis().setMaximum(10);
         plot.getY2Axis().setMinimum(0);
         plot.getY2Axis().setMaximum(10);        
         plot.getXAxis().setMinimum(0);
         plot.getXAxis().setMaximum(10);
         */
        plot.setLabelVisible(false);
        plot.setBackground(new Color(240, 240, 240));
        
        setLayout(new BorderLayout());
        add(plot);
        setPreferredSize(new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT));

        plot.setHeader(getTitle());
        plot.getY1Axis().setName(getAxis(AxisId.Y).getLabel());
        plot.getXAxis().setName(getAxis(AxisId.X).getLabel());
    }
    
    @Override
    protected void onTitleChanged() {
        plot.setHeader(getTitle());
        if(getTitleFont()!=null)
            plot.setHeaderFont(getTitleFont());        
    }

    @Override
    protected void onAxisLabelChanged(AxisId axis) {
        switch (axis){
            case X:
                plot.getXAxis().setName(getAxis(AxisId.X).getLabel());
                break;
            case Y:
                plot.getY1Axis().setName(getAxis(AxisId.Y).getLabel());
                break;

        }
    }   
    
    @Override
    protected void onAxisRangeChanged(AxisId axis_id) {
        JLAxis axis = null;
        switch (axis_id) {
            case X:
                axis = plot.getXAxis();
                break;
            case Y:
                axis = plot.getY1Axis();
                break;
            default:
            return;
        }
        axis.setAutoScale(getAxis(axis_id).isAutoRange());
        axis.setMinimum(getAxis(axis_id).getMin());
        axis.setMaximum(getAxis(axis_id).getMax());
        update(true);
    }
    

    @Override
    protected void createPopupMenu() {
        super.createPopupMenu();

        //Remove duplicated menu items
        JMenuItem dummy=new JMenuItem();
        plot.addMenuItem(dummy);      
        JPopupMenu menu = (JPopupMenu) dummy.getParent();
        for (int index=9;index>=6;index--)        
            menu.remove(index);        
        menu.remove(dummy);
        
    }

    @Override
    public void updateSeries(LinePlotSeries series) {
        doUpdate();//TODO
    }

    @Override
    public void doUpdate() {
        plot.repaint();
    }

    private void addKeyBindings() {
        //The zoom method  ois not doing what  I expecte, and no documentation...
        /*
         plot.setFocusable( true ); 
         plot.requestFocusInWindow();
         plot.addKeyListener(new KeyListener() {

         @Override
         public void keyTyped(KeyEvent e) {                
         }

         @Override
         public void keyPressed(KeyEvent e) {
         doUpdate();
         System.out.println("Total " + plot.getXAxis().getMinimum() + "->" + plot.getXAxis().getMaximum());
         System.out.println("Zoom  " + plot.getXAxis().getMin() + "->" + plot.getXAxis().getMax());
         if (plot.isZoomed()){
         if (e.getKeyCode()==KeyEvent.VK_RIGHT){                        
         double w = plot.getXAxis().getMax()-plot.getXAxis().getMin();
         double r = plot.getXAxis().getMax() + w/10;
         //r = Math.min(r,plot.getXAxis().getMaximum());
         plot.getXAxis().zoom((int)(r-w),(int)r);
         System.out.println("Zooming to " + ((int)(r-w)) + "-" + ((int)r));
         requestUpdate();                       

         }
         else if (e.getKeyCode()==KeyEvent.VK_LEFT){
         double w = plot.getXAxis().getMax()-plot.getXAxis().getMin();
         double l = plot.getXAxis().getMin() - w/10;
         //l = Math.max(l,plot.getXAxis().getMinimum());
         plot.getXAxis().zoom((int)l,(int)(l+w));
         System.out.println("Zooming to " + ((int)l) + "-" + ((int)(l+w)));
         requestUpdate();
         }
         }
         }

         @Override
         public void keyReleased(KeyEvent e) {
                
         }
         });
         */
    }

    protected void addPopupMenuItem(final JMenuItem item) {
        if (item == null) {
            plot.addSeparator();
        } else {
            plot.addMenuItem(item);
        }
    }

}
