package com.algobase.share.widgets;

import java.lang.reflect.Method;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;

import android.util.AttributeSet;


public class RotateView extends ViewGroup {

    float heading;
    float heading_delta;

    int[] screenLoc = new int[2];
/*
    int screen_width;
    int screen_height;
    int diagonal;
*/

    boolean rotate_events = true;

    Matrix matrix = new Matrix();

    View view;


  public RotateView(Context c) 
  { super(c); 
    initialize(c);
   }

  public RotateView(Context c, AttributeSet a) 
  { super(c,a);
    initialize(c);
   }

  public RotateView(Context c, AttributeSet a, int i) 
  { super(c,a,i); 
    initialize(c);
   }

  public int getScreenX() { return screenLoc[0]; }
  public int getScreenY() { return screenLoc[1]; }

  public void screenToView(float[] vec)
  { vec[0] -= screenLoc[0];
    vec[1] -= screenLoc[1];

    // rotation
    float x = 0.5f * getWidth() - screenLoc[0];
    float y = 0.5f * getHeight() - screenLoc[1];

    //float deg = (float)Math.toDegrees(-heading);
    float deg = (float)-heading;

    Matrix matrix = new Matrix();
    matrix.setRotate(deg,x,y);
    matrix.mapPoints(vec);
  }


   void initialize(Context context) {
        view = null;
/*
        DisplayMetrics dm = context.getResources().getDisplayMetrics();
        screen_width = dm.widthPixels;
        screen_height = dm.heightPixels;
        diagonal = (int) Math.hypot(screen_width,screen_height);
*/

        heading_delta = 11.25f; // 360/32
    }

    public void  setView(View v) 
    { if (view != null) removeView(view);
      view = v;
      addView(v,0);
     }

    public void  delView() 
    { if (view != null) removeView(view);
      view = null;
     }

    public float getHeading() { return heading; }

    public void setHeadingDelta(float delta) { heading_delta = delta; } 

    public void setRotateEvents(boolean b) { rotate_events = b; }

    public void rotate(float delta) { setHeading(heading + delta); }

    public void rotateNoAnim(float delta) { setHeadingNoAnim(heading + delta); }

    public void setHeadingNoAnim(float head) 
    { heading = head % 360.0f;
      invalidate();
    }

    public void setHeading(float head) 
    { 
      head = head % 360.0f;

      if (heading_delta == 0) return;

      synchronized (this) {
        float delta = head - heading;
        if (Math.abs(delta) < heading_delta) return; 

        heading = head;

        //invalidate();

        float target = 0;
        if (delta > +180) target = 360;
        if (delta < -180) target = -360;

        Animation anim = new RotateAnimation(delta,target,
                                          Animation.RELATIVE_TO_SELF,0.5f,
                                          Animation.RELATIVE_TO_SELF,0.5f);
      //long duration = Math.abs((long)(4000*delta/360));
      //long duration = Math.abs((long)(6000*delta/360));
        long duration = Math.abs((long)(8000*delta/360));

        if (duration > 2000) duration = 2000;

        anim.setDuration(duration);
        View view = (getChildCount() > 0) ? getChildAt(0) : this;
        view.setAnimation(anim);

        invalidate();
      }
    }
    
    

    @Override
    protected void dispatchDraw(Canvas canvas) {
        canvas.save();
        canvas.rotate(-heading, getWidth() * 0.5f, getHeight() * 0.5f);
        canvas.getMatrix().invert(matrix);
        super.dispatchDraw(canvas);
        canvas.restore();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        final int width = getWidth();
        final int height = getHeight();
        final int count = getChildCount();

        getLocationOnScreen(screenLoc);

        for (int i = 0; i < count; i++) {
            View view = getChildAt(i);
            int child_width = view.getMeasuredWidth();
            int child_height = view.getMeasuredHeight();
            int child_left = (width - child_width) / 2;
            int child_top = (height - child_height) / 2;
            view.layout(child_left, child_top, child_left + child_width, 
                                               child_top + child_height);
            if (i == 0)
            { //screenLoc[0] += child_left; 
              screenLoc[0] = child_left; // why ?
              screenLoc[1] += child_top;
             }
        }
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);

      int w = getMeasuredWidth();
      int h = getMeasuredHeight();
      int d = (int)Math.hypot(w,h);

      //setMeasuredDimension(d,d);

      int sizeSpec = MeasureSpec.makeMeasureSpec(d,MeasureSpec.EXACTLY);

      for (int i = 0; i < getChildCount(); i++) 
         getChildAt(i).measure(sizeSpec, sizeSpec);
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (rotate_events)
        { float[] vec = { event.getX(), event.getY() };
          matrix.mapPoints(vec);
          event.setLocation(vec[0], vec[1]);
         }
        return super.dispatchTouchEvent(event);
    }

}
