package uy.edu.fing.chesstrack;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener;
import org.opencv.android.JavaCameraView;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;

import uy.edu.fing.chesstrack.modulovision.Manager;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.Editable;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.EditText;

public class ChessTrackActivity extends Activity implements
		CvCameraViewListener {

	private static final String TAG = "CHESSTRACK::Activity";
	private static final String IPV4_REGEX = "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
	private static final String PORT_REGEX = "^(\\d{4,5})$";

	// estados
	private static final int IDLE = 0;
	private static final int CALIBRAR = 1;
	private static final int JUGAR = 2;

	private CameraBridgeViewBase _mOpenCvCameraView;
	// private JavaCameraView _mOpenCvCameraView;

	private Manager _manager;
	private MenuItem _mItemCalibrar;
	private MenuItem _mItemServer;
	private int _estado;

	private final BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(
			this) {

		@Override
		public void onManagerConnected(int status) {
			switch (status) {
			case LoaderCallbackInterface.SUCCESS: {
				Log.i(TAG, "OpenCV loaded successfully");
				_mOpenCvCameraView.enableView();
			}
				break;
			default: {
				super.onManagerConnected(status);
			}
				break;
			}
		}
	};

	@Override
	public void onResume() {
		super.onResume();
		OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9, this,
				mLoaderCallback);
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		Log.i(TAG, "called onCreate");
		super.onCreate(savedInstanceState);

		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		setContentView(R.layout.chess_track_layout);
		_mOpenCvCameraView = (JavaCameraView) findViewById(R.id.chess_track_layout);
		_mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
		_mOpenCvCameraView.setCvCameraViewListener(this);

		_manager = Manager.getInstance();
	}

	public void getServerIp() {
		AlertDialog.Builder alert = new AlertDialog.Builder(this);
		alert.setTitle("Communication Setup");
		alert.setMessage("Set server ip");

		final EditText input = new EditText(this);
		alert.setView(input);

		alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int whichButton) {
				Editable value = input.getText();
				if (value == null || value.toString().equals("")
						|| !value.toString().matches(IPV4_REGEX)) {
					Log.i(TAG, "INPUT= not valid IP" + value.toString());
					getServerIp();
				} else {
					Log.i(TAG, "INPUT=" + value.toString());

					Log.i(TAG, "IP=" + value.toString());
					getServerPort(value.toString());
				}
			}
		});

		alert.show();
	}

	public void getServerPort(final String ip) {
		AlertDialog.Builder alert = new AlertDialog.Builder(this);
		alert.setTitle("Communication Setup");
		alert.setMessage("Set server port");

		final EditText input = new EditText(this);
		alert.setView(input);

		alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int whichButton) {
				Editable value = input.getText();
				Log.i(TAG, "INPUT=" + value.toString());
				if (value == null || value.toString().equals("")
						|| !value.toString().matches(PORT_REGEX)) {
					Log.i(TAG, "INPUT= not valid PORT" + value.toString());
					getServerPort(ip);
				} else {
					Log.i(TAG, "INPUT=" + value.toString());

					int port = Integer.parseInt(value.toString());
					Log.i(TAG, "PORT=" + port);
					_manager.setConnection(ip, port);
				}
			}
		});

		alert.show();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		Log.i(TAG, "called onCreateOptionsMenu");
		_mItemCalibrar = menu.add("Calibrar..");
		_mItemServer = menu.add("Conectar Server");
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		Log.i(TAG, "Menu Item selected " + item);
		if (item == _mItemCalibrar) {
			if (_estado == IDLE) {
				_estado = CALIBRAR;
			}
		} else if (item == _mItemServer) {
			getServerIp();
		}
		return true;
	}

	@Override
	public void onPause() {
		super.onPause();
		if (_mOpenCvCameraView != null) {
			_mOpenCvCameraView.disableView();
		}
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if (_mOpenCvCameraView != null) {
			_mOpenCvCameraView.disableView();
		}
		if (_manager != null) {
			_manager.destroy();
		}
	}

	@Override
	public void onCameraViewStarted(int width, int height) {
	}

	@Override
	public void onCameraViewStopped() {
	}

	@Override
	public Mat onCameraFrame(Mat inputFrame) {
		if (inputFrame != null) {
			switch (_estado) {
			case CALIBRAR:
				Log.i(TAG, "calibrando...");
				if (_manager.calibrar(inputFrame)) {
					_manager.iniciarJuego();
					_estado = JUGAR;
				} else {
					_estado = IDLE;
				}
				break;
			case JUGAR:
				Log.i(TAG, "jugando...");
				_manager.processFrame(inputFrame);
				break;
			case IDLE:
				break;
			}
		}
		return inputFrame;
	}
}