package test;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

/*************
 * LineChart *
 *************
 *
 * Class generating line chart from added datas.
 *
 *
 * @author Pavel Novak
 * http//pavel-novak.net
 *
 * 2oo9
 */

public class LineChart {

    //public objects and variables
    public Color graphColor; //color of graph line
    public Color backgroundColor; //color of background
    public String windowName; //value of title window
    public float windowHeight; //height of window in px
    public float windowWidth; //width of window in px

    //private objects and variables
    private float[] cacheOfInputValues; //array whit elements
    private float minInputValue; //minimal value of input
    private float maxInputValue; //maximum value of input
    private paintComponent component = new paintComponent(); //create component

    //basic constructor StreamLineChart(min, max)
    public LineChart(int minInputValue, int maxInputValue) {

        this.minInputValue = minInputValue;
        this.maxInputValue = maxInputValue;
        this.setFeaturesToStandard(); //setting other features to standard
        cacheOfInputValues = completeArray(); //completing array
        paramTest(); //testing input parameters
    }

    //second constructor StreamLineChart(min, max, graphClr, bgClr, winName)
    public LineChart(int minInputValue, int maxInputValue, Color graphColor,
           Color backgroundColor, String windowName, int wWidth, int wHeight) {

        this.minInputValue = minInputValue;
        this.maxInputValue = maxInputValue;
        this.graphColor = graphColor;
        this.backgroundColor = backgroundColor;
        this.windowName = windowName;
        this.windowHeight = wHeight;
        this.windowWidth = wWidth;
        cacheOfInputValues = completeArray(); //completing array
        paramTest(); //testing input parameters
    }

    //method adding new element to array cacheOfInputValues
    public void addElement(int inputElement) {

        //input control test
        if(inputElement < minInputValue || inputElement > maxInputValue)
            throw new UnsupportedOperationException("Input element " +
                    "is not in the range permitted values!");
        rewindArray(); //ready to add new element to array
        cacheOfInputValues[199] = calculateOneElementIsPixels(inputElement);
        component.repaint();
    }

    //method creating draw window
    public void drawChart() {

        JFrame frame = new JFrame(windowName); //create frame
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        component.setBackground(backgroundColor); //set bg color
        frame.getContentPane().add(component); //adding paint comp.
        frame.setSize((int)windowWidth, (int)windowHeight); //window size
        frame.setResizable(false); //set rezisable to false
        frame.setVisible(true); //set window to visible
    }

    //method setting features to standard options
    private void setFeaturesToStandard() {

        this.graphColor = Color.GREEN; //default green
        this.backgroundColor = Color.BLACK; //default black color on BG
        this.windowName = new String("LineChart window"); //window title
        this.windowHeight = 480; //default window height
        this.windowWidth = 640; //default window width
    }

    //method completing array whit elements under window
    private float[] completeArray() {

        float[] preparedArray = new float[200];
        float value = calculateOneElementIsPixels((int)minInputValue);
        for(int i = 0;i < 200;i++) {
            preparedArray[i] = value;
        }
        return preparedArray; //returned array whit same values
    }

    //method rewinding array one value left
    private void rewindArray() {

        float[] cacheArray = cacheOfInputValues; //copy array
        for(int i = 0;i < 199;i++) {

            cacheOfInputValues[i] = cacheArray[i+1];
        }
    }

    //method testing input parameters datas
    private void paramTest() {

        if(minInputValue > maxInputValue || minInputValue == maxInputValue)
            throw new UnsupportedOperationException("Bad input parameters!");
        if(windowWidth < 200)
            throw new UnsupportedOperationException("Window width is low!");
    }

    //method getting how much pixels is one value
    private float calculateOneElementIsPixels(int inputElement) {

        float elementPercent = (float) 100 - ( (float) 100 / (maxInputValue
                - minInputValue)) * (inputElement - minInputValue);
        float elementPixels = ( (windowHeight-100) / 100 * elementPercent);
        return elementPixels;
    }

    //class wiht painting component
    private class paintComponent extends JPanel {



        //painting method
        public void paint(Graphics g) {

            //minInputValue convert to String
            String minInputValueStr = Integer.toString((int)minInputValue);
            //minInputValue convert to String
            String maxInputValueStr = Integer.toString((int)maxInputValue);
            //lower line height in px
            float lowerLineHeight = (calculateOneElementIsPixels(
                                    (int) minInputValue) + 31);
            //elemenet width in px
            float elementWidthpx = (float) ((windowWidth / 200) - 0.3);
            super.paintComponent(g); //paint component
            Graphics2D g2d = (Graphics2D)g; //Graphics2D object
            g2d.setColor(Color.GRAY); //set grid and text color
            //draw lower line
            g2d.draw(new Line2D.Double(0,lowerLineHeight,windowWidth-40,
                    lowerLineHeight));
            //draw right line
            g2d.draw(new Line2D.Double(windowWidth-62,30,
                                    windowWidth-62, lowerLineHeight+20));
            //draw minInputValue description
            g2d.drawString(minInputValueStr, windowWidth-55, windowHeight-55);
            //draw maxInputValue description
            g2d.drawString(maxInputValueStr, windowWidth-55, 40);
            g2d.setColor(graphColor); //set chart color
            //paint chart
            for(int i = 0; i < 199; i++) {
                //draw abscissa
                g2d.draw(new Line2D.Double(elementWidthpx * i,
                        cacheOfInputValues[i]+30, elementWidthpx * (i+1),
                        cacheOfInputValues[i+1]+30));
            }
        }
    }
}