package org.geuz.onelab;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Fragment;
import android.graphics.Bitmap;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.os.Handler;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.util.TypedValue;

public class ModelFragment extends Fragment{

    private Gmsh _gmsh;
    private mGLSurfaceView _glView;
    private TextView _progress;
    private LinearLayout _progressLayout;
    private LinearLayout _controlBarLayout;
    private GestureDetector _gestureDetector;
    private Timer _animation;
    private Handler _hideDelay;
    private SeekBar _animationStepper;

    final Runnable hideControlsRunnable = new Runnable() {
            public void run() { hideControlBar(); }
        };

    public static ModelFragment newInstance(Gmsh g)
    {
        ModelFragment fragment = new ModelFragment();
        Bundle bundle = new Bundle();
        bundle.putParcelable("Gmsh", g);
        fragment.setArguments(bundle);
        return fragment;
    }

    public ModelFragment() { }

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        _gmsh = getArguments().getParcelable("Gmsh");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState)
    {
        View rootView = inflater.inflate(R.layout.fragment_model, container, false);
        RelativeLayout glViewLayout = (RelativeLayout)rootView.findViewById(R.id.glViewLayout);
        GLESRender renderer = new GLESRender(_gmsh);
        _glView = new mGLSurfaceView(glViewLayout.getContext(), renderer);
        _glView.setEGLContextClientVersion(1);
        _glView.setRenderer(renderer);
        _glView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
        _glView.requestRender();
        _hideDelay = new Handler();
        _gestureDetector = new GestureDetector(getActivity(), new OnGestureListener() {
                // UNUSED Auto-generated method stub
                public boolean onSingleTapUp(MotionEvent e) { return false; }
                // UNUSED Auto-generated method stub
                public void onShowPress(MotionEvent e) {}
                // UNUSED Auto-generated method stub
                public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                        float distanceX, float distanceY) { return false; }
                // UNUSED Auto-generated method stub
                public void onLongPress(MotionEvent e) {}
                // UNUSED Auto-generated method stub
                public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                                       float velocityY) { return false; }
                // UNUSED Auto-generated method stub
                public boolean onDown(MotionEvent e) { return false; }
            });
        _gestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {
                public boolean onSingleTapConfirmed(MotionEvent e) {
                    if(View.VISIBLE == _controlBarLayout.getVisibility())
                        hideControlBar();
                    else
                        showControlBar();
                    return true;
                }
                // UNUSED Auto-generated method stub
                public boolean onDoubleTapEvent(MotionEvent e) { return false; }
                // UNUSED Auto-generated method stub
                public boolean onDoubleTap(MotionEvent e) { return false; }
            });
        _glView.setOnTouchListener(new View.OnTouchListener() {
                public boolean onTouch(View v, MotionEvent event) {
                    return _gestureDetector.onTouchEvent(event);
                }
            });
        glViewLayout.addView(_glView);
        RelativeLayout topRightLayout = new RelativeLayout(container.getContext());
        ImageButton rotationButton = new ImageButton(container.getContext());
        rotationButton.setBackgroundResource(R.drawable.icon_rotate);
        rotationButton.setLayoutParams(new LinearLayout.LayoutParams(60, 60));
        rotationButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    boolean rotate = !_glView.getRotate();
                    ((ImageButton)v).setBackgroundResource(rotate ?
                                                           R.drawable.icon_translate :
                                                           R.drawable.icon_rotate);
                    _glView.setRotate(rotate);
                }
            });
        topRightLayout.addView(rotationButton);
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams
            (RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);

        TypedValue tv = new TypedValue();
        int actionBarHeight = 80;
        if(container.getContext().getTheme().resolveAttribute
           (android.R.attr.actionBarSize, tv, true)){
            actionBarHeight = TypedValue.complexToDimensionPixelSize
                (tv.data, getResources().getDisplayMetrics());
        }
        layoutParams.setMargins(0, actionBarHeight + 20, 20, 0);
        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        glViewLayout.addView(topRightLayout, layoutParams);
        _progressLayout = new LinearLayout(container.getContext());
        ProgressBar bar = new ProgressBar(container.getContext());
        bar.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    _progress.setAlpha((_progress.getAlpha() > 0) ? 0 : 1);
                }
            });
        _progressLayout.addView(bar);
        _progress = new TextView(container.getContext());
        _progressLayout.setAlpha(0);
        _progressLayout.setGravity(Gravity.CENTER);
        _progressLayout.addView(_progress);
        layoutParams = new RelativeLayout.LayoutParams
            (RelativeLayout.LayoutParams.WRAP_CONTENT,
             RelativeLayout.LayoutParams.WRAP_CONTENT);
        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        glViewLayout.addView(_progressLayout, layoutParams);
        _controlBarLayout = (LinearLayout) getActivity().getLayoutInflater()
            .inflate(R.layout.control_bar, null);
        final ImageButton prevButton = (ImageButton)_controlBarLayout.findViewById(R.id.controlPrev);
        final ImageButton playPauseButton = (ImageButton)_controlBarLayout.findViewById(R.id.controlPlay);
        final ImageButton nextButton = (ImageButton)_controlBarLayout.findViewById(R.id.controlNext);
        _animationStepper = (SeekBar)_controlBarLayout.findViewById(R.id.controlStepper);
        _animationStepper.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                // UNUSED Auto-generated method stub
                public void onStopTrackingTouch(SeekBar seekBar) {}
                // UNUSED Auto-generated method stub
                public void onStartTrackingTouch(SeekBar seekBar) {}
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                    if(fromUser) {
                        postDelay();
                        _gmsh.setAnimation(progress);
                        requestRender();
                    }
                }
            });
        _controlBarLayout.setEnabled(false);
        playPauseButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    postDelay();
                    if(((ImageButton)v).getContentDescription().equals("play")) {
                        ((ImageButton)v).setContentDescription("pause");
                        ((ImageButton)v).setImageResource(android.R.drawable.ic_media_pause);
                        _animationStepper.setMax(_gmsh.numberOfAnimation()-1);
                        _animation = new Timer();
                        _animation.schedule(new TimerTask() {
                                public void run()  {
                                    _animationStepper.setProgress(_gmsh.animationNext());
                                    requestRender();
                                } }, 0, 500);
                        prevButton.setEnabled(false);
                        nextButton.setEnabled(false);
                    }
                    else {
                        ((ImageButton)v).setContentDescription("play");
                        ((ImageButton)v).setImageResource(android.R.drawable.ic_media_play);
                        _animation.cancel();
                        prevButton.setEnabled(true);
                        nextButton.setEnabled(true);
                    }
                }
            });
        nextButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    postDelay();
                    _animationStepper.setProgress(_gmsh.animationNext());
                    requestRender();
                }
            });
        prevButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    postDelay();
                    _animationStepper.setProgress(_gmsh.animationPrev());
                    requestRender();
                }
            });
        layoutParams = new RelativeLayout.LayoutParams(
                                                       RelativeLayout.LayoutParams.MATCH_PARENT,
                                                       RelativeLayout.LayoutParams.WRAP_CONTENT);
        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        glViewLayout.addView(_controlBarLayout, layoutParams);
        this._controlBarLayout.setVisibility(View.INVISIBLE);
        return rootView;
    }
    public void postDelay(int delay)
    {
        _hideDelay.removeCallbacks(hideControlsRunnable);
        _hideDelay.postDelayed(hideControlsRunnable, delay);
    }
    public void postDelay()
    {
        this.postDelay(6000);
    }
    public void showControlBar()
    {
        if(getActivity() == null || ((MainActivity)getActivity()).isComputing() ||
           !_gmsh.haveAnimation()) return;
        _controlBarLayout.setEnabled(true);
        _animationStepper.setMax(_gmsh.numberOfAnimation()-1);
        this.postDelay();
        Animation bottomUp = AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in);
        _controlBarLayout.setVisibility(View.VISIBLE);
        _controlBarLayout.startAnimation(bottomUp);
    }
    public void hideControlBar()
    {
        if(getActivity() == null || View.INVISIBLE == _controlBarLayout.getVisibility()) return;
        _hideDelay.removeCallbacks(hideControlsRunnable);
        Animation bottomDown = AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out);
        _controlBarLayout.startAnimation(bottomDown);
        _controlBarLayout.setVisibility(View.INVISIBLE);

    }
    public void showProgress(String progress)
    {
        _progressLayout.setAlpha(1);
        _progress.setText(progress);
    }
    public void hideProgress()
    {
        _progressLayout.setAlpha(0);
        _progress.setText("");
    }
    public void requestRender()
    {
        _glView.requestRender();
    }
    public void takeScreenshot(File out)
    {
        Bitmap screenshot = _glView.getScreenshot();
        try {
            FileOutputStream f = new FileOutputStream(out);
            screenshot.compress(Bitmap.CompressFormat.PNG, 85, f);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        finally {
            _glView.setDrawingCacheEnabled(false);
        }
    }
}
