package com.example.shengwutanzhen;

import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.menu.MenuBuilder;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class RandomActivity extends AppCompatActivity implements SensorEventListener {

    private SensorManager sensorManager;
    private Sensor accelerometer;
    private Sensor magnetometer;
    private Sensor gyroscope;
    private Handler handler;
    private Runnable sensorRunnable;

    private String uuid;
    private String gesture;
    private String gesture_phone;
    private String randomString;

    private long beginTime;

    private static final String TAG = "RandomActivity";

    private List<Float> touchSize = new ArrayList<>();

    private List<Float> accelerometerValues = new ArrayList<>();

    private List<Long> accelerometerTime = new ArrayList<>();
    private List<Long> magnetometerTime = new ArrayList<>();
    private List<Long> gyroscopeTime = new ArrayList<>();

    private List<Float> magnetometerValues = new ArrayList<>();

    private List<Float> gyroscopeValues = new ArrayList<>();
    private List<Float> distanceMoveList = new ArrayList<>();
    private IEditText edit_random;
    private TextView tv_string;
    private IKeyboardView keyboardView_random;

    long pointerDownTime = 0;
    long pointerUpTime = 0;
    private List<Long> gapList = new ArrayList<>();

    private List<Float> pressures = new ArrayList<>();

    private List<Float> offsetList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_random);
        beginTime = System.currentTimeMillis();
        initView();

        randomString = getRandomString();
        tv_string.setText(randomString);
        tv_string.setTextSize(20);
        tv_string.setTextColor(getResources().getColor(R.color.text_color));

        Bundle bundle = getIntent().getExtras();
        assert bundle != null;
        uuid = bundle.getString("uuid");
        gesture = bundle.getString("gesture");
        gesture_phone = bundle.getString("gesture_phone");

        startSensorUpdates();

        keyboardView_random.setOnTouchListener((view, motionEvent) -> {
            if (motionEvent.getAction() == MotionEvent.ACTION_DOWN){
                onPointerDown(motionEvent);
            } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
                onPointerUp(motionEvent);
            }
            return false;
        });

        //默认绑定一个
        keyboardView_random.setEditText(edit_random);
        edit_random.setmIKeyboardView(keyboardView_random);

        setListener();
    }

    private void initView(){
        edit_random = findViewById(R.id.edit_random);
        tv_string = findViewById(R.id.tv_string);
        keyboardView_random = findViewById(R.id.keyboardview_random);
    }

    private void startSensorUpdates() {
        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

        if (sensorManager != null) {
            accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            magnetometer = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
            gyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
        }


        handler = new Handler(Looper.getMainLooper());
        sensorRunnable = new Runnable() {
            @Override
            public void run() {
                // Register sensors with SENSOR_DELAY_FASTEST
                if (accelerometer != null) {
                    sensorManager.registerListener(RandomActivity.this, accelerometer, SensorManager.SENSOR_DELAY_FASTEST);
                }
                if (magnetometer != null) {
                    sensorManager.registerListener(RandomActivity.this, magnetometer, SensorManager.SENSOR_DELAY_FASTEST);
                }
                if (gyroscope != null) {
                    sensorManager.registerListener(RandomActivity.this, gyroscope, SensorManager.SENSOR_DELAY_FASTEST);
                }

                // Schedule the next run
                handler.postDelayed(this, 10);
            }
        };
    }

    private void setListener() {
        findViewById(R.id.confirm_btn_random).setOnClickListener(view -> {
            stopSensorUpdates();
            if (!edit_random.getText().toString().equals(randomString)){
                Toast.makeText(RandomActivity.this, "输入不匹配，请重新输入", Toast.LENGTH_SHORT).show();
                return;
            }
            long now = System.currentTimeMillis();
            if (now - beginTime > 1000*60) {
                Toast.makeText(RandomActivity.this, "请在60秒内完成输入", Toast.LENGTH_SHORT).show();
                onBackPressed();
                return;
            }
            int length = edit_random.getText().toString().length();
            Map<String, Object> map = new HashMap<>();
            map.put("uuid", uuid);
            map.put("gesture", gesture);
            map.put("gesture_phone", gesture_phone);
            map.put("gapList", gapList);
            map.put("offsetList", offsetList);
            map.put("distanceMoveList", distanceMoveList);
            map.put("str_len", length);
            map.put("pressures", pressures);
            map.put("touch_size",touchSize);
            map.put("accelerometer_data", accelerometerValues);
            map.put("accelerometer_time", accelerometerTime);
            map.put("gyroscope_data", gyroscopeValues);
            map.put("gyroscope_time", gyroscopeTime);
            map.put("magnetometer_data", magnetometerValues);
            map.put("magnetometer_time", magnetometerTime);
            map.put("input_duration", now - beginTime);
            map.put("data_stamp", now);
            map.put("is_ios", false);
            new SendPostRequestTask().execute(map);
        });
    }
    @Override
    protected void onResume() {
        super.onResume();
        handler.post(sensorRunnable);
    }

    public String getRandomString() {
        int length = 8 + new Random().nextInt(8);
        String charSet = "qwertyuiopasdfghjklzxcvbnm1234567890";
        StringBuilder randomStr = new StringBuilder();
        for (int i = 0; i < length; i++) {
            randomStr.append(charSet.charAt(new Random().nextInt(charSet.length())));
        }
        return randomStr.toString();
    }

    private void stopSensorUpdates() {
        sensorManager.unregisterListener(this);
        handler.removeCallbacks(sensorRunnable);
    }

    @Override
    protected void onPause() {
        super.onPause();
        handler.removeCallbacks(sensorRunnable);
        sensorManager.unregisterListener(this);
    }

    public void onPointerDown(MotionEvent event) {
        float size = event.getSize();
        float pressure = event.getPressure();
        pressures.add(pressure);
        touchSize.add(size);
        Log.i(TAG,"onPointerDown:size ="+size);
        // Get the current time in milliseconds and assign it to pointerDownTime to represent the time when the pointer is pressed
        pointerDownTime = System.currentTimeMillis();

        // If pointerUpTime is not 0 (indicating the time the pointer was last lifted), add the interval between pointerDownTime and pointerUpTime to the gapList

        if (pointerUpTime != 0) {
            gapList.add(pointerDownTime - pointerUpTime);
        }

        // Ensure that the gapList length is consistent with twice the length of charList
        int length = edit_random.getText().toString().length();
        if (gapList.size() != length * 2) {
            gapList = gapList.subList(0, length * 2);
        }

        // Save the position where the pointer is pressed (x and y coordinates) in the offsetList
        offsetList.add(event.getRawX());
        Log.i(TAG,"onPointerDown: dx ="+(event.getRawX()));
        offsetList.add(event.getRawY());
        Log.i(TAG,"onPointerDown: dy ="+(event.getRawY()));
    }

    public void onPointerUp(MotionEvent event) {
        pointerUpTime = System.currentTimeMillis();

        // 点击持续时间
        if (pointerDownTime != 0) {
            gapList.add(pointerUpTime - pointerDownTime);
        }

        // 保存点击本次 keyButton 的偏移量
        double dxPointerDown = 0;
        double dyPointerDown = 0;
        if (offsetList.size() >= 2) {
            dyPointerDown = offsetList.remove(offsetList.size() - 1);
            dxPointerDown = offsetList.remove(offsetList.size() - 1);
        }
        float templeDx = event.getRawX();
        float templeDy = event.getRawY();
        float distanceMove = (float) Math.sqrt(Math.pow(templeDx - dxPointerDown, 2) + Math.pow(templeDy - dyPointerDown, 2));
        distanceMoveList.add(distanceMove);
        Log.i(TAG, "onPointerUp: distanceMove = "+ distanceMove);
        float dx = (float) Math.abs((templeDx + dxPointerDown) / 2);
        float dy = (float) Math.abs((templeDy + dyPointerDown) / 2);
        offsetList.add(dx);
        Log.i(TAG,"onPointerUp: dx ="+templeDx);
        offsetList.add(dy);
        Log.i(TAG,"onPointerUp: dy ="+templeDy);

        // 除去在屏幕滑动的偏移量
        if (offsetList.size() != (gapList.size() + 1)) {
            try {
                offsetList = offsetList.subList(0, gapList.size() + 1);
            } catch (IndexOutOfBoundsException e) {
                // 处理异常情况，例如显示提示信息
                Toast.makeText(RandomActivity.this, "不要胡乱点击呀", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            accelerometerTime.add(System.currentTimeMillis());
            accelerometerValues.add(event.values[0]);
            accelerometerValues.add(event.values[1]);
            accelerometerValues.add(event.values[2]);
            Log.i(TAG,"onSensorChanged: accelerometerValues"+event.values[0]+","+event.values[1]+","+event.values[2]);
            // 处理加速计的值
        } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            magnetometerTime.add(System.currentTimeMillis());
            magnetometerValues.add(event.values[0]);
            magnetometerValues.add(event.values[1]);
            magnetometerValues.add(event.values[2]);
            Log.i(TAG,"onSensorChanged: magnetometerValues"+event.values[0]+","+event.values[1]+","+event.values[2]);
            // 处理磁力计的值
        } else if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
            gyroscopeTime.add(System.currentTimeMillis());
            gyroscopeValues.add(event.values[0]);
            gyroscopeValues.add(event.values[1]);
            gyroscopeValues.add(event.values[2]);
            Log.i(TAG,"onSensorChanged: gyroscopeValues"+event.values[0]+","+event.values[1]+","+event.values[2]);
            // 处理陀螺仪的值
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int i) {

    }
    private class SendPostRequestTask extends AsyncTask<Map<String, Object>, Void, String> {
        @Override
        protected String doInBackground(Map<String, Object>... params) {
            try {
                Map<String, Object> data = params[0];
                HttpClient client = HttpClient.getInstance();
                return client.sendPostRequest("http://36.108.213.190:10011/random", data);
            } catch (Exception e) {
                return e.getMessage();
            }
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
//            Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
            Bundle bundle = new Bundle();
            bundle.putString("result", result);
            Intent intent = new Intent(RandomActivity.this, ResultActivity.class);
            intent.putExtras(bundle);
            startActivity(intent);
        }
    }
}