import * as React from "react";
import { View, Text } from "react-native";
import {
  StudentStatusFilterType,
  LocationType,
  subjectUserMapType,
  StudentStatusListType,
  StudentStatusFilterTypeFlattened,
} from "../../interfaces/Interfaces";
import { Double, Float } from "react-native/Libraries/Types/CodegenTypes";

export default function ParseStudyGroupList(
  data: any,
  user_location: LocationType
) {
  // Circle generation for students in a study group
  let result: any[] = [];
  // We first remove any instances that do not have a study group associated with it
  let data_filtered = data.filter(
    (item: StudentStatusFilterType) =>
      item.study_group !== undefined && item.study_group.length > 0
  );
  // console.log("Filtered Data:", data_filtered);
  // Then we flatten the data so that all attributes are in the first layer
  // We first flatten the data to remove nested entries
  let data_flattened = data_filtered.map((item: StudentStatusFilterType) => ({
    active: item.active,
    distance: item.distance,
    landmark: item.landmark,
    latitude: item.location.latitude,
    longitude: item.location.longitude,
    study_group: item.study_group,
    subject: item.subject,
    user: item.user,
    weight: 1,
  }));
  // console.log("Flattened Data:", data_flattened);

  // We take from the array all unique study groups
  let unique_studygroups = [
    ...new Set(
      data_flattened.map((item: StudentStatusFilterType) => item.study_group)
    ),
  ];

  // Then we create arrays unique to each subject
  unique_studygroups.forEach((studygroup, index: number) => {
    // We build another array for each subject, including only those instances that are the same subject name
    let unique_subject_list = data_flattened
      .filter(
        (item: StudentStatusFilterTypeFlattened) =>
          item.study_group === studygroup
      )
      .map((item: StudentStatusFilterTypeFlattened) => ({
        active: item.active,
        distance: item.distance,
        landmark: item.landmark,
        latitude: item.latitude,
        longitude: item.longitude,
        study_group: item.study_group,
        subject: item.subject,
        user: item.user,
        weight: 1,
      }));

    /*
    let unique_subject_object = data_flattened.filter(
      (item: StudentStatusFilterTypeFlattened) => item.subject === subject
    );
    */

    // We get the circle's center by averaging all the points
    // Calculate the average latitude and longitude
    const totalLat = unique_subject_list.reduce(
      (sum: Double, point: LocationType) => sum + point.latitude,
      0
    );
    const totalLng = unique_subject_list.reduce(
      (sum: Double, point: LocationType) => sum + point.longitude,
      0
    );

    let avgLat = totalLat / unique_subject_list.length;
    let avgLng = totalLng / unique_subject_list.length;

    // console.log("Center Latitude:", avgLat);
    // console.log("Center Longitude:", avgLng);

    // Haversine Distance Function
    function haversineDistance(
      lat1: number,
      lon1: number,
      lat2: number,
      lon2: number
    ) {
      function toRad(x: number) {
        return (x * Math.PI) / 180;
      }

      lat1 = toRad(lat1);
      lon1 = toRad(lon1);
      lat2 = toRad(lat2);
      lon2 = toRad(lon2);

      let dLat = lat2 - lat1;
      let dLon = lon2 - lon1;

      let a =
        Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.cos(lat1) *
          Math.cos(lat2) *
          Math.sin(dLon / 2) *
          Math.sin(dLon / 2);
      let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

      // Multiply by Earth's radius (in kilometers) to obtain distance
      let distance = 6371 * c;

      // Convert to meters
      return distance * 1000;
    }

    // We now calculate the radius of the circle using the Haversine Distance Formula
    // For each entry, we calculate the Haversine Distance from the user's location.
    // The largest value is used as the circle radius

    let circle_radius = Math.max(
      ...unique_subject_list.map(
        (item: StudentStatusFilterTypeFlattened, index: number) => {
          let distance = haversineDistance(
            item.latitude,
            item.longitude,
            user_location.latitude,
            user_location.longitude
          );

          /*console.log(
            "Haversine Distance for entry #",
            index + 1,
            ":",
            distance
          );*/
          return distance;
        }
      )
    );
    // console.log("Radius:", circle_radius);

    // We now build the object that we will return
    const subjectUserMap: subjectUserMapType = {
      subject: "",
      study_group: "",
      users: [],
      latitude: 0,
      longitude: 0,
      radius: 0,
    };
    unique_subject_list.forEach((item: StudentStatusFilterType) => {
      if (!subjectUserMap["users"]) {
        subjectUserMap["users"] = [];
      }
      if (!subjectUserMap["study_group"]) {
        subjectUserMap["study_group"] = unique_subject_list[0].study_group;
      }
      subjectUserMap["subject"] = item.subject;
      subjectUserMap["latitude"] = avgLat;
      subjectUserMap["longitude"] = avgLng;
      subjectUserMap["radius"] = circle_radius;
      subjectUserMap["users"].push(item.user);
    });
    console.log(subjectUserMap);

    result = result.concat([subjectUserMap]);
  });

  console.log("Final Result:", result);

  return result;
}
