import { NativeModules, NativeEventEmitter } from "react-native";
import React from "react";
import { useSelector } from "react-redux";
import reactotron from "reactotron-react-native";
import RNFetchBlob from "rn-fetch-blob";
import { SELFSURVEYSERVICE_DOCUMENT_URL } from "../Api/ApiUrls";
import { async } from "validate.js";
import Database from "../../../../Components/common/Database";
import DeviceInfo from "react-native-device-info";
import {
  firebaseAttributes,
  errorRecord,
  firebaseEvents,
} from "../common/libEventLog/libCrashlytics/libCrashlyticsEvent";
const iOS = Platform.OS === "ios";
const { getImei } = require("react-native-imei");

let realm = Database.getRealm();
var PILocation = realm.objects("PILocation");
var currentLatitude = PILocation[0]?.lat;
var currentLongitude = PILocation[0]?.long;

const interval = 5000;
var acceTimestamp = undefined;
var gyroTimestamp = undefined;
var magnetoTimestamp = undefined;
var compassTimestamp = undefined;

import sensors, {
  setUpdateIntervalForType,
  SensorTypes,
} from "react-native-sensors";
import { map, filter } from "rxjs/operators";
import StepcounterIosAndroid from "react-native-stepcounter-ios-android";
import { Alert } from "react-native";

var accelerometerData = [];
var gyroscopeData = [];
var magnetometerData = [];
var pedometerData = [];
var compassData = [];
var SensorDataInfo;
var deviceName = "NA";
var MAC = "NA";
var IP = "NA";
var IMEInumber = "NA";
var APILevel;
var count;
//sensors
let accSubscription, gyroSubscription, magSubscription, gravSubscription;
//Set update interval
function setUpdateIntervals() {
  if (!DeviceInfo.isEmulatorSync()) {
    setUpdateIntervalForType(SensorTypes.accelerometer, 10000); // defaults to 100ms
    setUpdateIntervalForType(SensorTypes.gyroscope, 10000); // defaults to 100ms
    setUpdateIntervalForType(SensorTypes.magnetometer, 10000); // defaults to 100ms
    setUpdateIntervalForType(SensorTypes.gravity, 10000); // defaults to 100ms
  }
}

export function unsubscribeSensors() {
  if (!DeviceInfo.isEmulatorSync()) {
    // If it's the last subscription to accelerometer it will stop polling in the native API
    accSubscription && accSubscription.unsubscribe();
    gyroSubscription && gyroSubscription.unsubscribe();
    magSubscription && magSubscription.unsubscribe();
    gravSubscription && gravSubscription.unsubscribe();
    StepcounterIosAndroid && StepcounterIosAndroid.stopStepCounter();
  }
}

// capcture sensor data
export function startCapturingSensorData(int) {
  cleanSensorDataArr();

  if (DeviceInfo.isEmulatorSync()) {
    Alert.alert(
      "Emulator detected!",
      "Sensors may not be available on emulator. Data won't be sent."
    );
  }
  setUpdateIntervals();
  //Accelerometer
  if (sensors.accelerometer !== undefined) {
    accSubscription = sensors.accelerometer.subscribe(
      ({ x, y, z, timestamp }) => {
        if (acceTimestamp === undefined) {
          acceTimestamp = timestamp;
        } else if (timestamp > acceTimestamp + interval) {
          console.log("accelerometer added : " + timestamp);
          acceTimestamp = timestamp;
          accelerometerData.push({
            x: x,
            y: y,
            z: z,
            timestamp: timestamp,
          });
        }
      }
    );
  }
  if (sensors.gyroscope !== undefined) {
    gyroSubscription = sensors.gyroscope.subscribe(({ x, y, z, timestamp }) => {
      if (gyroTimestamp === undefined) {
        gyroTimestamp = timestamp;
      } else if (timestamp > gyroTimestamp + interval) {
        console.log("gyroscope added : " + timestamp);
        gyroTimestamp = timestamp;
        gyroscopeData.push({
          x: x,
          y: y,
          z: z,
          timestamp: timestamp,
        });
      }
    });
  }
  if (sensors.magnetometer !== undefined) {
    magSubscription = sensors.magnetometer.subscribe(
      ({ x, y, z, timestamp }) => {
        if (magnetoTimestamp === undefined) {
          magnetoTimestamp = timestamp;
        } else if (timestamp > magnetoTimestamp + interval) {
          console.log("magnetometer added : " + timestamp);
          magnetoTimestamp = timestamp;
          magnetometerData.push({
            x: x,
            y: y,
            z: z,
            timestamp: timestamp,
          });
        }
      }
    );
  }
}
if (sensors.gravity !== undefined) {
  gravSubscription = sensors.gravity.subscribe(({ x, y, z, timestamp }) => {
    if (gyroTimestamp === undefined) {
      gyroTimestamp = timestamp;
    } else if (timestamp > gyroTimestamp + interval) {
      console.log("gyroscope added : " + timestamp);
      gyroTimestamp = timestamp;
      compassData.push({
        x: x,
        y: y,
        z: z,
        timestamp: timestamp,
      });
    }
  });

  //Pedometer
  StepcounterIosAndroid.isSupported()
    .then((result) => {
      if (result) {
        console.log("Sensor TYPE_STEP_COUNTER is supported on this device");

        const myModuleEvt = new NativeEventEmitter(
          NativeModules.StepcounterIosAndroid
        );
        myModuleEvt.addListener("StepCounter", (data) => {
          console.log("STEPS", data.steps);
          pedometerData.push({
            step: data.steps,
            timestamp: new Date().getTime(),
          });
        });

        StepcounterIosAndroid.startStepCounter();
      } else {
        console.log("Sensor TYPE_STEP_COUNTER is not supported on this device");
      }
    })
    .catch((err) => console.log(err));
}
// genrate sensor data
export async function genrateSensorFile(
  activityId,
  activityTypeId,
  licensePlateNumber,
  quoteNumber,
  sensorImageDetails,
  callback
) {
  const date = new Date().getDate();
  const month = new Date().getMonth() + 1;
  const year = new Date().getFullYear();

  //Time calulation for the display on preciew Screen
  const hour = new Date().getHours();
  const minute = new Date().getMinutes();
  const seconds = new Date().getSeconds();

  SensorDataInfo = {
    activity_id: activityId,
    activity_type: activityTypeId,
    date_time:
      year +
      " " +
      month +
      " " +
      date +
      "  " +
      hour +
      ":" +
      minute +
      ":" +
      seconds,
    imageDetails: sensorImageDetails,
    policy_no: quoteNumber,
    reg_no: licensePlateNumber,
    sensor_data: {
      accelerometers: accelerometerData,
      compass: compassData,
      gyroscope: gyroscopeData,
      magnetometers: magnetometerData,
      millis: new Date().getTime(),
      pedometer: pedometerData,
    },
  };
  const filename = activityId + "_" + "Sensor.json";
  const destPath = RNFetchBlob.fs.dirs.CacheDir + "/" + filename;
  var data = await RNFetchBlob.fs.writeFile(
    destPath,
    JSON.stringify(SensorDataInfo, null, "  "),
    "utf8"
  );
  await uploadSensorData(
    "file://" + destPath,
    activityId,
    activityTypeId,
    callback
  );
  RNFetchBlob.fs.exists(destPath).then((data) => {
    console.log("IS EXIST  >> ", data);
  });
  cleanSensorDataArr();
  unsubscribeSensors();
}

export const cleanSensorDataArr = () => {
  accelerometerData = [];
  gyroscopeData = [];
  magnetometerData = [];
  pedometerData = [];
  compassData = [];
};

const getDeviceInfo = () => {
  try {
    if (iOS) {
      console.log("iOS doesn't provide device details");
      return;
    }
    DeviceInfo.getDeviceName().then((DeviceName) => {
      deviceName = DeviceName;
    });

    DeviceInfo.getMacAddress().then((mac) => {
      MAC = mac;
    });
    DeviceInfo.getIpAddress().then((ip) => {
      IP = ip;
    });

    DeviceInfo.getApiLevel().then((apiLevel) => {
      APILevel = apiLevel;
      if (apiLevel > 28) {
        DeviceInfo.getAndroidId().then((androidId) => {
          IMEInumber = androidId;
        });
      } else {
        getImei().then((imeiList) => {
          IMEInumber = imeiList;
        });
      }
    });
  } catch (error) {
    console.log("Error in SensorData.js getDeviceInfo() ", error);
  }
};

//upload sensor data file
const uploadSensorData = async (uri, activityId, activityTypeId, callback) => {
  try {
    await getDeviceInfo();
    console.log("@@@@@@@@@@@@@@@@@", deviceName, APILevel, IP, IMEInumber, MAC);
    const xhr = new XMLHttpRequest();
    const formData = new FormData();
    console.log("Sensor TO BE UPLOADED > > >   ", uri);
    const handleProgress = (event) => {
      reactotron.log(Math.round(event.loaded * 100) / event.total);
    };
    const documentUploadData = {
      activityId: activityId,
      data: null,
      dataUploadStatus: 0,
      fullName: activityId + "_" + "Sensor",
      geoLocation: {
        isBlocked: "",
        deviceName: deviceName,
        latitude: currentLatitude,
        longitude: currentLongitude,
        operatingSystem: APILevel,
        timezone: "Asia/Kolkata",
        deviceTime: null,
        ipAddress: IP,
        deviceIMEI: IMEInumber,
        macAddress: MAC,
        documentSource: "DigitEdge",
      },
      isLast: "false",
      isLastData: "false",
      isLastDocument: "false",
      isSurveyor: "false",
      manualOdometerReading: "",
      source: "DIGITEDGE",
    };
    console.log(
      "!!!!!!!!!!!!!!!!!!!!",
      JSON.stringify(documentUploadData, null, "  ")
    );
    formData.append("file", {
      uri: uri,
      type: "image/jpeg",
      fileName: activityId + "_" + "Sensor",
      name: activityId + "_" + "Sensor.json",
    });
    formData.append("documentData", JSON.stringify(documentUploadData));

    xhr.upload.addEventListener("progress", handleProgress);
    xhr.addEventListener("load", async () => {
      console.log("Sensor Data Uploaded");
      console.log("Sensor Data STATUS  > > >", xhr.status);
      if (xhr.status == 200) {
        await callback();
        firebaseEvents(
          "sensorFile_Uploaded",
          { resp: xhr.status },
          activityId,
          activityTypeId,
          ""
        );
      } else {
        count = count + 1;
        if (count <= 2) {
          genrateSensorFile();
          firebaseEvents(
            "sensorFile_Upload_retry",
            {
              resp: xhr.status,
              count: count,
            },
            activityId,
            activityTypeId,
            ""
          );
        } else {
          await callback();
          firebaseEvents(
            "sensorFile_not_uploaded",
            {
              resp: xhr.status,
              count: count,
            },
            activityId,
            activityTypeId
          );
        }
      }
      firebaseAttributes(
        "Uploaded Image :" +
          activityId +
          "_" +
          "Sensor.json" +
          "\n" +
          documentUploadData
      );
    });
    xhr.open("POST", SELFSURVEYSERVICE_DOCUMENT_URL);
    xhr.setRequestHeader(
      "Accept",
      "*/*",
      "Content-Type",
      "multipart/form-data"
    );
    xhr.send(formData);
  } catch (error) {
    console.log("Error in Upload Sensor Data ", error);
  }
};
