"use client";
import React, { useState, useEffect } from 'react';
//import top_tags from "@/data/top_tags.json";
import positions from "@/data/positions.json";
import server_matrix from "@/data/server_matrix.json";
import server_names from "@/data/server_names.json";
import tag_names from "@/data/tag_names.json";

interface Tag {
  index: number;
  tag: string;
}
// Read from data/top_tags.json FILE
//const tags: Tag[] = 

const selected_tags = [
  "politics", "gardening", "art", "nature", "pride", "cycling", "climate",
  "programming", "dogs", "privacy", "cats", "gaming", "education",
  "science", "music", "movies", "food", "books", "lgbtq", "python",
  "emacs", "gay", "trans", "furry", "photography", "cooking", "literature",
  "television"
];


function dotProduct(a: number[], b: number[]): number {
  return a.map((x, i) => x * b[i]).reduce((sum, current) => sum + current, 0);
}

function magnitude(arr: number[]): number {
  return Math.sqrt(arr.map(x => x * x).reduce((sum, current) => sum + current, 0));
}

function cosineSimilarity(arr1: number[], arr2: number[]): number {
  if (arr1.length !== arr2.length) {
      throw new Error("Arrays must have the same length");
  }

  const dotProd = dotProduct(arr1, arr2);
  const magnitudeProd = magnitude(arr1) * magnitude(arr2);
  if (magnitudeProd === 0) {
      return 0;
  }
  return dotProd / magnitudeProd;
}

function averageOfArrays(arr: number[][]): number[] {
  // Get the length of the first sub-array
  const length = arr[0].length;

  // Initialize an array to store the sums
  const sums = Array(length).fill(0);

  // Loop over each sub-array
  for (let i = 0; i < arr.length; i++) {
    // Loop over each element in the sub-array
    for (let j = 0; j < arr[i].length; j++) {
      // Add the element to the corresponding sum
      sums[j] += arr[i][j];
    }
  }

  // Divide each sum by the number of arrays to get the average
  const averages = sums.map(sum => sum / arr.length);

  return averages;
}



const TagSelector: React.FC = () => {
  //const top_tags: Tag[] = [];
  const all_tags: Tag[] = tag_names.map((tag: string, index: number) => ({index, tag}))
  const tags: Tag[] = all_tags.filter((tag: Tag) => selected_tags.includes(tag.tag));
  //top_tags.filter((tag) => selected_tags.includes(tag.tag));
  // State to keep track of selected tag IDs.
  const [selectedTagIds, setSelectedTagIds] = useState<number[]>([]);

  const [suggestedTagIds, setSuggestedTagIds] = useState<number[]>([]);

  const [topServerIds, setTopServerIds] = useState<number[]>([]);

  // Function to handle tag selection toggling.
  const toggleTag = (tagId: number) => {
    setSelectedTagIds((currentTagIds) =>
      currentTagIds.includes(tagId)
        ? currentTagIds.filter((id) => id !== tagId)
        : [...currentTagIds, tagId],
    )
  };

  function find_most_similar_tags(all_tags: Tag[], selectedTagIds: number[], positions: number[][]) {
    let most_similar: Tag[] = [];
    // get the average position of all selected tags
    if (selectedTagIds.length > 0) {
      // loop through all selected tags and get their positions
      const selected_positions = selectedTagIds.map((tagId) => positions[tagId]);
      for (let i = 0; i < selected_positions.length; i++) {
        let tag_similarity = positions.map((row) => cosineSimilarity(selected_positions[i], row));
        let tag_rank = tag_similarity.map((similarity, index) => ({index, similarity})).sort((a, b) => b.similarity - a.similarity).map((item, index) => ({index: item.index, similarity: item.similarity, name: tag_names[item.index]}));
        console.log(tag_rank.slice(0, 10));
        let topServerIds = tag_rank.slice(0, 10).map((item) => item.index);
        for (let tagId of all_tags.filter((tag) => topServerIds.includes(tag.index))) {
          if (!selectedTagIds.includes(tagId.index) && !most_similar.includes(tagId)) {
            most_similar.push(tagId);
          }
        }
      }
    }
    return most_similar;
  }

  useEffect(() => {
    // get the average position of all selected tags
    if (selectedTagIds.length > 0) {
      let selected_positions = selectedTagIds.map((tagId) => positions[tagId]);
      // get the average of selected positions
      let average_position = averageOfArrays(selected_positions);
      // loop through each row of the server_matrix and calculate the cosine similarity
      const server_similarity = server_matrix.map((row) => cosineSimilarity(average_position, row));
      const server_rank = server_similarity.map((similarity, index) => ({index, similarity})).sort((a, b) => b.similarity - a.similarity).map((item, index) => ({index: item.index, similarity: item.similarity, name: server_names[item.index]}));
      setTopServerIds(server_rank.slice(0, 10).map((item) => item.index));

      // Find the most similar tags among all tags
      const tag_similarity = all_tags.map((tag) => ({t: tag, sim: cosineSimilarity(average_position, positions[tag.index])})).sort((a, b) => b.sim - a.sim);
      const most_similar = find_most_similar_tags(all_tags, selectedTagIds, positions);
      //tag_similarity.slice(0, 50).map((item) => item.t);
      console.log(most_similar);
      setSuggestedTagIds(most_similar.map((tag) => tag.index));
      console.log(suggestedTagIds);
    }
  }, [selectedTagIds]);

  return (
    <div>
      <div className="flex flex-wrap gap-2">
        <div>
          <h3>Selected</h3>
          {all_tags.filter((tag) => selectedTagIds.includes(tag.index)).map((tag) => (
            <button
              key={tag.index}
              onClick={() => toggleTag(tag.index)}
              className={`px-3 py-1 rounded-full text-sm ${
                selectedTagIds.includes(tag.index) ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-800'
              } transition-colors duration-300 ease-in-out focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-opacity-50`}
            >
              {tag.tag}
            </button>
          ))}
        </div>
        <div>
          <h3>Categories</h3>
          {tags.filter((tag) => !selectedTagIds.includes(tag.index)).map((tag) => (
              <button
                key={tag.index}
                onClick={() => toggleTag(tag.index)}
                className={`px-3 py-1 rounded-full text-sm bg-gray-200 text-gray-800 transition-colors duration-300 ease-in-out focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-opacity-50`}
              >
                {tag.tag}
              </button>
            ))}
        </div>
        <div>
          <h3>Suggested Tags ({suggestedTagIds.filter((tag) => !selectedTagIds.includes(tag)).length})</h3>
          {all_tags.filter((tag) => suggestedTagIds.includes(tag.index)).filter((tag) => !selectedTagIds.includes(tag.index)).map((tag) => (
              <button
                key={tag.index}
                onClick={() => toggleTag(tag.index)}
                className={`px-3 py-1 rounded-full text-sm bg-gray-200 text-gray-800 transition-colors duration-300 ease-in-out focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-opacity-50`}
              >
                {tag.tag}
              </button>
            ))}
        </div>
      </div>
      <div>
        <ul>
          {topServerIds.map((id) => (
            <li key={id}>{server_names[id]}</li>
          ))}
        </ul>
      </div>
    </div>
  );
};


export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <TagSelector />
    </main>
  );
}
