package sliz.elektromery;

import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.PointLabelFormatter;
import com.androidplot.xy.PointLabeler;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.XYSeries;

import java.text.DecimalFormat;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.text.*;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Shader;
import android.os.Bundle;
import android.util.FloatMath;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;



public class GraphActivity extends Activity implements OnTouchListener{

    private XYPlot mySimpleXYPlot;
//    private Button resetButton;
    private SimpleXYSeries series = null;
    
    double maxVal = 0;
    double minVal = Double.MAX_VALUE;
    long maxDate = 0;
    long minDate = Long.MAX_VALUE;
    
    double maxVal2 = 0;
    double minVal2 = Double.MAX_VALUE;
    long maxDate2 = 0;
    long minDate2 = Long.MAX_VALUE;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
//		getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
//				WindowManager.LayoutParams.FLAG_SECURE);
		super.onCreate(savedInstanceState);

		// Remove title bar
		this.requestWindowFeature(Window.FEATURE_NO_TITLE);
		// Remove notification bar
		this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);

		setContentView(R.layout.graph_view);

		mySimpleXYPlot = (XYPlot) findViewById(R.id.mySimpleXYPlot);
        mySimpleXYPlot.setOnTouchListener(this);
        
        List<MyData> list = DatabaseActivity.getDataList();
        
        Number[] numSightings = new Number[list.size()];
        Number[] years = new Number[list.size()];
        
        for(int i = 0 ; i < list.size() ; i++)
        {
        	Double newNum = Double.parseDouble((list.get(i).Values));
        	
        	if(maxVal < newNum)maxVal = newNum;
        	if(minVal > newNum)minVal = newNum;
        	numSightings[i] = (Number)newNum;
        	
        	long newDate = list.get(i).DateMS;
        	if(maxDate < newDate)maxDate = newDate;
        	if(minDate > newDate)minDate = newDate;
        	years[i] = newDate;
        }

        // create our series from our array of nums:
        series = new SimpleXYSeries(
                Arrays.asList(years),
                Arrays.asList(numSightings),
                "Datum");
        
        maxVal2 = maxVal;
        minVal2 = minVal;
        maxDate2 = maxDate;
        minDate2 = minDate;
        
        double step = (maxVal - minVal)/3;
        mySimpleXYPlot.setRangeBoundaries(minVal-step, maxVal+step, BoundaryMode.FIXED);
        
        long step2 = (maxDate - minDate)/3;
        mySimpleXYPlot.setDomainBoundaries(minDate-step2, maxDate+step2, BoundaryMode.FIXED);

        // Create a formatter to use for drawing a series using LineAndPointRenderer:
//        LineAndPointFormatter series1Format = new LineAndPointFormatter(
//                Color.rgb(0, 100, 0),                   // line color
//                Color.rgb(0, 100, 0),                   // point color
//                Color.rgb(100, 200, 0));                // fill color
 
        // setup our line fill paint to be a slightly transparent gradient:
        Paint lineFill = new Paint();
        lineFill.setAlpha(200);
        lineFill.setShader(new LinearGradient(0, 0, 0, 250, Color.GRAY, Color.RED, Shader.TileMode.MIRROR));
        
        PointLabelFormatter plf = new PointLabelFormatter(Color.CYAN);
 
        LineAndPointFormatter lnpf = new LineAndPointFormatter(Color.rgb(0, 0, 200), null, null, plf);
        
        lnpf.setPointLabeler(new PointLabeler() {
        	private SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm dd.MM yyyy");
    	    @Override
    	    public String getLabel(XYSeries series, int index) {
    	    	
    	    	Number yNum = series.getX(index);
    	    	if(yNum == null) return "";
    	    	    	    	
    	    	long timestamp = yNum.longValue();
                Date date = new Date(timestamp);
                String ret = dateFormat.format(date); 
                return ret;
    	    }
    	});
        
        mySimpleXYPlot.getGraphWidget().setPaddingRight(2);
		mySimpleXYPlot.addSeries(series, lnpf);
		
		mySimpleXYPlot.setTitle("Spotřeba v závislosti na čace");
 
        // draw a domain tick for each year:
//        mySimpleXYPlot.setDomainStep(XYStepMode.SUBDIVIDE, years.length);
        
        // rotate domainlabel
        mySimpleXYPlot.getGraphWidget().setDomainLabelOrientation(-30);
        
		// disable legend
		mySimpleXYPlot.getLegendWidget().setVisible(false);
 
        // get rid of decimal points in our range labels:
        mySimpleXYPlot.setRangeValueFormat(new DecimalFormat("0"));
 
        // X axis format
        mySimpleXYPlot.setDomainValueFormat(new Format() {
 
            // create a simple date format that draws on the year portion of our timestamp.
            // see http://download.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html
            // for a full description of SimpleDateFormat.
            private SimpleDateFormat dateFormat = new SimpleDateFormat("MM yyyy");
 
            @Override
            public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
 
                // because our timestamps are in seconds and SimpleDateFormat expects milliseconds
                // we multiply our timestamp by 1000:
                long timestamp = ((Number) obj).longValue();
                Date date = new Date(timestamp);
                return dateFormat.format(date, toAppendTo, pos);
            }
 
            @Override
            public Object parseObject(String source, ParsePosition pos) {
                return null;
 
            }
        });
        

        
//		mySimpleXYPlot.redraw();
//		mySimpleXYPlot.calculateMinMaxVals();
//		minXY = new PointF(mySimpleXYPlot.getCalculatedMinX().floatValue(),
//				mySimpleXYPlot.getCalculatedMinY().floatValue());
//		maxXY = new PointF(mySimpleXYPlot.getCalculatedMaxX().floatValue(),
//				mySimpleXYPlot.getCalculatedMaxY().floatValue());

		// Create events
		createEvents();

	}

	// Definition of the touch states
    static final int NONE = 0;
    static final int ONE_FINGER_DRAG = 1;
    static final int TWO_FINGERS_DRAG = 2;
    int mode = NONE;

    PointF firstFinger;
    float distBetweenFingers;
    boolean stopThread = false;

    @Override
    public boolean onTouch(View arg0, MotionEvent event) {
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN: // Start gesture
                firstFinger = new PointF(event.getX(), event.getY());
                mode = ONE_FINGER_DRAG;
                stopThread = true;
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;
            case MotionEvent.ACTION_POINTER_DOWN: // second finger
                distBetweenFingers = spacing(event);
                // the distance check is done to avoid false alarms
                if (distBetweenFingers > 5f) {
                    mode = TWO_FINGERS_DRAG;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == ONE_FINGER_DRAG) {
                    PointF oldFirstFinger = firstFinger;
                    firstFinger = new PointF(event.getX(), event.getY());
                    scroll(oldFirstFinger.x - firstFinger.x);
//                    mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x,
//                            BoundaryMode.FIXED);
                    double step = (maxVal - minVal)/3;
                    mySimpleXYPlot.setRangeBoundaries(minVal-step, maxVal+step, BoundaryMode.FIXED);
                    
                    long step2 = (maxDate - minDate)/3;
                    mySimpleXYPlot.setDomainBoundaries(minDate-step2, maxDate+step2, BoundaryMode.FIXED);
                    mySimpleXYPlot.redraw();

                } else if (mode == TWO_FINGERS_DRAG) {
                    float oldDist = distBetweenFingers;
                    distBetweenFingers = spacing(event);
                    zoom(oldDist / distBetweenFingers);
//                    mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x,
//                            BoundaryMode.FIXED);
                    double step = (maxVal - minVal)/3;
                    mySimpleXYPlot.setRangeBoundaries(minVal-step, maxVal+step, BoundaryMode.FIXED);
                    
                    long step2 = (maxDate - minDate)/3;
                    mySimpleXYPlot.setDomainBoundaries(minDate-step2, maxDate+step2, BoundaryMode.FIXED);
                    mySimpleXYPlot.redraw();
                }
                break;
        }
        
        
        return true;
    }

    private void zoom(float scale) {
    	Log.i("Touch", "ZOOM scale = " + scale);
    	long dif = (long) ((maxDate-minDate)/30);
    	long lastMax = maxDate, lastMin = minDate;
    	if(scale < 1)
    	{
	    	minDate += dif;
	    	maxDate -= dif;
    	}
    	else
    	{
	    	minDate -= dif;
	    	maxDate += dif;
    	}	
    	if(minDate < minDate2)
    	{
    		minDate = minDate2;
    		maxDate = lastMax;
    	}
    	if(maxDate > maxDate2)
    	{
    		maxDate = maxDate2;
    		minDate = lastMin;
    	}
    }

    private void scroll(float pan) {
    	Log.i("Touch", "Scroll pan = " + pan);
    	long dif = (long) (Math.abs(pan)*(maxDate-minDate)/150);
    	if(pan > 0)
    	{
	    	minDate += dif;
	    	maxDate += dif;
    	}
    	else
    	{
	    	minDate -= dif;
	    	maxDate -= dif;
    	}
    	if(minDate < minDate2)
    	{
    		minDate = minDate2;
    		maxDate += dif;
    	}
    	if(maxDate > maxDate2)
    	{
    		maxDate = maxDate2;
    		minDate -= dif;
    	}
    }

    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }
    
	private void createEvents() {
		Button btnBack = (Button) findViewById(R.id.btn_back);
		btnBack.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				backToDatabase();
			}
		});
		
		Button btnRes = (Button) findViewById(R.id.btn_reset);
		btnRes.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				maxVal = maxVal2;
		        minVal = minVal2;
		        maxDate = maxDate2;
		        minDate = minDate2;
		        
		        double step = (maxVal - minVal)/3;
		        mySimpleXYPlot.setRangeBoundaries(minVal-step, maxVal+step, BoundaryMode.FIXED);
		        
		        long step2 = (maxDate - minDate)/3;
		        mySimpleXYPlot.setDomainBoundaries(minDate-step2, maxDate+step2, BoundaryMode.FIXED);
		        mySimpleXYPlot.redraw();
			}
		});
	}

	private void backToDatabase() {
		Intent intnscnd = new Intent(GraphActivity.this, DatabaseActivity.class);
		startActivity(intnscnd);
		GraphActivity.this.finish();
	}
	
	 @Override
	    public boolean onKeyDown(int keyCode, KeyEvent event) 
	    {
		    if(keyCode == KeyEvent.KEYCODE_BACK) 
		    {
		    	backToDatabase();
		    }
		    	
	    	//Pass other events along their way up the chain
		    return super.onKeyDown(keyCode, event);
	    }
}
