package com.supermap.interfaces.ar.rajawali;


import android.content.Context;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;

import org.rajawali3d.cameras.Camera;
import org.rajawali3d.math.Quaternion;
import org.rajawali3d.math.vector.Vector3;

public class TouchViewHandler {

    private static final int TOUCH_THIRD_PITCH_LIMIT = 60;
    private static final int TOUCH_THIRD_PITCH_DEFAULT = 45;
    private static final int TOUCH_THIRD_YAW_DEFAULT = -45;
    private static final int TOUCH_FOV_MAX = 120;
    private static final int TOUCH_THIRD_DISTANCE = 10;
    private static final int TOUCH_TOP_DISTANCE = 10;

    private static final float FIRST_PERSON_FOV = 37.8f;
    private static final int THIRD_PERSON_FOV = 65;
    private static final int TOP_DOWN_FOV = 65;

    private ViewMode viewMode = ViewMode.THIRD_PERSON;//默认第三人称视角

    private GestureDetector gestureDetector;
    private ScaleGestureDetector scaleGestureDetector;

    private Vector3 topDownCameraDelta = new Vector3();
    private float thirdPersonPitch = TOUCH_THIRD_PITCH_DEFAULT;
    private float thirdPersonYaw = TOUCH_THIRD_YAW_DEFAULT;

    private Camera camera;

    public TouchViewHandler(Context context, Camera camera) {
        gestureDetector = new GestureDetector(context, new DragListener());
        scaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener());
        this.camera = camera;
    }

    public Camera getCamera() {
        return camera;
    }

    public void setCamera(Camera camera) {
        this.camera = camera;
    }

    public void updateCamera(Vector3 position, Quaternion orientation) {
        if (viewMode == ViewMode.FIRST_PERSON) {
            camera.setPosition(position);
            camera.setOrientation(orientation);
        } else if (viewMode == ViewMode.TOP_DOWN) {
            camera.setPosition(position.x + topDownCameraDelta.x, TOUCH_TOP_DISTANCE,
                    position.z + topDownCameraDelta.z);
            camera.setRotation(Vector3.Axis.X, 90);
        } else if (viewMode == ViewMode.THIRD_PERSON) {
            camera.setPosition(position.x, position.y, position.z);
            camera.setRotZ(thirdPersonPitch);
            camera.rotate(Vector3.Axis.Y, thirdPersonYaw);
            camera.moveForward(TOUCH_THIRD_DISTANCE);
        }
    }

    public void onTouchEvent(MotionEvent motionEvent) {
        gestureDetector.onTouchEvent(motionEvent);
        scaleGestureDetector.onTouchEvent(motionEvent);
    }

    public ViewMode getViweMode() {
        return viewMode;
    }

    public void setFirstPersonView() {
        viewMode = ViewMode.FIRST_PERSON;
        camera.setFieldOfView(FIRST_PERSON_FOV);
    }

    public void setTopDownView() {
        viewMode = ViewMode.TOP_DOWN;
        topDownCameraDelta = new Vector3();
        camera.setFieldOfView(TOP_DOWN_FOV);
    }

    public void setThirdPersonView() {
        viewMode = ViewMode.THIRD_PERSON;
        thirdPersonYaw = TOUCH_THIRD_YAW_DEFAULT;
        thirdPersonPitch = TOUCH_THIRD_PITCH_DEFAULT;
        camera.setFieldOfView(THIRD_PERSON_FOV);
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        float scale = 1f;

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            scale = detector.getScaleFactor();
            scale = Math.max(0.1f, Math.min(scale, 5f));

            camera.setFieldOfView(
                    Math.min(camera.getFieldOfView() / scale, TOUCH_FOV_MAX));

            return true;
        }
    }

    private class DragListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

            if (viewMode == ViewMode.TOP_DOWN) {
                double factor = camera.getFieldOfView() / 45;
                topDownCameraDelta.add(
                        new Vector3(distanceX / 100 * factor, 0, distanceY / 100 * factor));
            } else if (viewMode == ViewMode.THIRD_PERSON) {
                thirdPersonPitch -= distanceY / 10;
                thirdPersonPitch =
                        Math.min(thirdPersonPitch, TOUCH_THIRD_PITCH_LIMIT);
                thirdPersonPitch =
                        Math.max(thirdPersonPitch, -TOUCH_THIRD_PITCH_LIMIT);
                thirdPersonYaw -= distanceX / 10;
                thirdPersonYaw %= 360;
            }

            return true;
        }
    }
}