package fanch.multijeu.numbers.widget;

import android.app.Activity;
import android.content.Context;
import android.support.annotation.CallSuper;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;

import fanch.multijeu.common.exceptions.BadChildClass;
import fanch.multijeu.numbers.data.Expression;
import fanch.multijeu.numbers.data.ExpressionSet;
import fanch.multijeu.numbers.data.NumberExpr;

public abstract class CalcWidget extends GridLayout  implements View.OnClickListener {
    protected TextView   mScreen;
    protected CalcButton mClear;
    protected CalcButton mUndo;
    protected CalcButton mValid;
    protected CalcButton mAdd;
    protected CalcButton mMult;
    protected CalcButton mSub;
    protected int        mMinGridHeight=3;


    protected CalcButton mOperandes[];
    protected CalcButton mControl[];
    protected ArrayList<CalcButton> mNumbers = new ArrayList<CalcButton>();
    protected TypeState mState= TypeState.IDLE;

    protected AssistedCalcWidget.CalcWidgetListener mListener;

    public static interface CalcWidgetListener {
        void onValid();
        void onClear();
        void onUndo();
        void onExpressionDone(Expression expr);
        void onAnimEnd();
    }

    protected enum TypeState {
        IDLE,       //au début ou après un clear
        ON_NUMBER,  //apres qu'on ai tappé sur un nombre
        ON_OP,      //apres une operation
        RESULT      //apres le résultat
    }

    protected static class State {
        TypeState state;
        ArrayList<CalcButton> expression;
        ArrayList<CalcButton.CalcButtonState> states;
    }


    public CalcWidget(Context context) {
        super(context);
    }

    public CalcWidget(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    protected void clearNumbers()
    {
        final int count = mNumbers.size();
        for(int i=count-1; i>=0; i--)
        {
            removeView(mNumbers.get(i));
            mNumbers.remove(i);
        }
    }



    protected abstract void updateShow();
    public abstract Expression getResult();

    public void setNumbers(int x[])
    {
        for(int i=0; i<x.length; i++)
            addNumber(x[i]);
    }

    public void setNumbers(Expression x[])
    {
        for(int i=0; i<x.length; i++)
            addNumber(x[i]);
    }



    public void setNumbers(ExpressionSet x)
    {
        setNumbers(x.allowedNumber);
    }

    @Override
    public void onClick(View v) {
        if( !(v instanceof CalcButton) )
            throw new BadChildClass("Need to be CalcButton");
        final CalcButton.CalcButtonContent cb = ((CalcButton)v).getContent();
        switch(cb.type)
        {
            case CLEAR:
                onClear();
                break;
            case VALID:
                onValid();
                break;
            case NUMBER:
                onNumber(((CalcButton)v));
                break;
            case OPERATION:
                onOperation(((CalcButton)v));
        }
    }


    private void onValid()
    {
        valid();
    }

    protected void onClear() {
        clear();
    }

    protected void onNumber(CalcButton v)
    {
        number(v);
    }

    protected void onOperation(CalcButton v)
    {
        operation(v);
    }

    protected abstract void clear();
    protected abstract void valid();
    protected abstract void number(CalcButton v);
    protected abstract void operation(CalcButton v);

    @CallSuper
    protected void initControlButton()
    {

        mScreen = new TextView(getContext());
        mScreen.setTextSize(30);
        mScreen.setBackgroundColor(0x80000000);
        mScreen.setLayoutParams(new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT));
        mScreen.setText("");
        mScreen.setPadding(8,8,8,8);
        mScreen.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
        addView(mScreen);

        mClear=new CalcButton(getContext());
        mClear.setClear();
        mClear.setOnClickListener(this);


        mUndo=new CalcButton(getContext());
        mUndo.setUndo();
        mUndo.setOnClickListener(this);

        mValid=new CalcButton(getContext());
        mValid.setValid();
        mValid.setOnClickListener(this);

        mAdd=new CalcButton(getContext());
        mAdd.setAdd();
        mAdd.setOnClickListener(this);

        mSub=new CalcButton(getContext());
        mSub.setSub();
        mSub.setOnClickListener(this);

        mMult=new CalcButton(getContext());
        mMult.setMult();
        mMult.setOnClickListener(this);


        mControl = new CalcButton[]{mClear, mUndo, mValid};
        mScreen.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);

        addView(mClear);
        addView(mUndo);
        addView(mValid);
        addView(mAdd);
        addView(mSub);
        addView(mMult);
    }

    protected void addNumber(int x)
    {
        CalcButton cb = newButton(x);
        addView(cb);
        cb.setVisibility(GONE);
        mNumbers.add(cb);
        requestLayout();
    }

    protected void addNumber(Expression x)
    {
        CalcButton cb = newButton(x.compute());
        cb.setVisibility(GONE);
        addView(cb);
        mNumbers.add(cb);
        requestLayout();
    }


    protected CalcButton newButton(int x)
    {
        CalcButton cb = new CalcButton(getContext());
        cb.setNumber(new NumberExpr(x));
        cb.setOnClickListener(this);
        return cb;
    }

    protected void showNumber(final int i)
    {
        if(i<mNumbers.size())
        {
            final CalcButton btn = mNumbers.get(i);
            int w = ((Activity)getContext()).getWindow().getDecorView().getHeight();
            Animation animation = new TranslateAnimation(0, 0,512, 0);
            animation.setDuration(500);
            animation.setAnimationListener(new Animation.AnimationListener() {
                public void onAnimationStart(Animation animation) {}
                public void onAnimationEnd(Animation animation) {
                    showNumber(i+1);
                }
                public void onAnimationRepeat(Animation animation) {}
            });
            btn.setVisibility(VISIBLE);
            btn.startAnimation(animation);
        } else {
            if(mListener!=null)
                mListener.onAnimEnd();
        }
    }

    protected void onControlLayout(int w, int h)
    {
        for(int i=0; i<mControl.length; i++)
            mControl[i].setLayoutParams(new LayoutParams(i,1));
    }

    protected void onScreenLayout(int w, int h)
    {
        if(mScreen!=null)
        {
            mScreen.measure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST));
            LayoutParams lp = new LayoutParams(0,0, 4,1);
            int wm = w-mScreen.getMeasuredWidth();
            int hm=h-mScreen.getMeasuredHeight();
            lp.marin_right=wm/2;
            lp.marin_left=wm/2;
            lp.marin_top=hm/4;
            lp.marin_bottom=hm/2;
            mScreen.setLayoutParams(lp);
        }
    }

    protected void onOperandeLayout(int w, int h)
    {
        for(int i=0; i<mOperandes.length; i++)
            mOperandes[i].setLayoutParams(new LayoutParams(3,i+1));
    }

    protected void onNumberLayout(int w, int h)
    {
        for(int i=0; i<mNumbers.size(); i++)
        {
            final int x =  (i%3);
            final int y =  2+(i/3);
            mNumbers.get(i).setLayoutParams(new LayoutParams(x,y));
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        final int count = getChildCount();
        final int W = r-l;
        final int H = b-t;
        int h = 3;
        //if(count>0 && count<=12)

        if(mNumbers.size()%mMinGridHeight==0)
            h=(mNumbers.size()/3)+2;
        else
            h=(mNumbers.size()/3)+3;

        if(h<mMinGridHeight) h=mMinGridHeight;

        setGridDimension(4,h);
        onScreenLayout(W,H/h);
        onControlLayout(W,H/h);
        onOperandeLayout(W,H/h);
        onNumberLayout(W,H/h);

        super.onLayout(changed, l,t,r,b);
    }

    @Override
    protected void onMeasure(int ww, int hh) {
        final int w = MeasureSpec.getSize(ww);
        final int wm = MeasureSpec.getMode(ww);
        final int h = MeasureSpec.getSize(hh);
        final int hm = MeasureSpec.getMode(hh);

        //int size=(w<h)?(w/getGridWidth()):(h/getGridHeight());


       /* setMeasuredDimension(size*getGridWidth(),
                size*getGridHeight());*/
        setMeasuredDimension(w,h);
    }

    public void setListener(CalcWidgetListener mListener) {
        this.mListener = mListener;
    }
}
