import { MediaElement, MyHeader, MediaContainer } from "./elements";
import { splitByTitle, splitByYear } from "./functions";

import * as elements from "../elementcreate";




var sortType = 0;
var listType = 0;

const sortTypeTitle = 0;
const sortTypeYear = 1;
const sortTypeId = 2;

const moviesType = 0;
const gamesType = 1;
const seriesType = 2;

var listButtons: Array<HTMLElement | null> = [];
var sortButtons: Array<HTMLElement | null> = [];

var root: HTMLElement | null;
var editButton: HTMLElement | null;
var movieElements: HTMLElement[] = [];

function getLink(): string {
  switch (listType) {
    case moviesType:
      return "/api/media/movies";
    case gamesType:
      return "/api/media/games";
    case seriesType:
      return "/api/media/series";
  }
  return "/api/media/movies";
}

function submitMedia(event: SubmitEvent) {
  event.preventDefault();

  const pass = document.getElementById("pass") as HTMLInputElement | null;
  if (!pass) return;

  const input_id = document.getElementById("input_id") as HTMLInputElement | null;
  if (!input_id) return;


  if (pass.value == "" || input_id.value == "") return;


  fetch(getLink(), {
    body: JSON.stringify({ pass: pass.value, code: input_id.value }),
    headers: { "Content-Type": "application/json" },
    method: "POST"
  })
    .then(async (response) => {
      if (response.status != 201) {
        const json = await response.json();
        console.log(json);
        alert(json.message);
        return;
      }

      const movie: Movie = await response.json();
      var letter = movie.title[0].toUpperCase();
      if (!isNaN(parseInt(letter))) letter = "#";

      const mediaElement = <MediaElement webImg={movie.webImg} title={movie.title} released={movie.released} id={movie.code} fun={removeMedia} imageError={onImgError} />;

      const container = document.getElementById(letter);
      if (!container) {
        root?.appendChild(<MyHeader title={letter} />);
        root?.appendChild(<MediaContainer id={letter}>{mediaElement}</MediaContainer>);
        return
      };
      container.appendChild(mediaElement);

      movieElements.push(mediaElement);
    })
    .catch(err => {
      console.log(err);
    });

  input_id.value = "";
}

function loadState() {
  const searchParams = new URLSearchParams(window.location.search);
  if (searchParams.has("listType")) {
    switch (searchParams.get("listType")) {
      case "movies":
        listType = moviesType;
        break;
      case "series":
        listType = seriesType;
        break;
      case "games":
        listType = gamesType;
        break;
      default:
        listType = moviesType;
        break;
    }
  }

  if (searchParams.has("sortType")) {
    switch (searchParams.get("sortType")) {
      case "title":
        sortType = sortTypeTitle;
        break;
      case "year":
        sortType = sortTypeYear;
        break;
      case "id":
        sortType = sortTypeId;
        break;
      default:
        sortType = sortTypeTitle;
        break;
    }
  }
}

/** 
 * @param {number} type 
 */
function changeType(type: number) {
  listType = type;
  loadPage();
  const searchParams = new URLSearchParams(window.location.search);
  switch (listType) {
    case moviesType:
      searchParams.set("listType", "movies");
      break;
    case gamesType:
      searchParams.set("listType", "games");
      break;
    case seriesType:
      searchParams.set("listType", "series");
      break;
  }
  history.replaceState({}, '', window.location.pathname + '?' + searchParams.toString());
}

/**
 * @param {number} type 
 */
function changeSort(type: number) {
  sortType = type;
  loadPage();
  const searchParams = new URLSearchParams(window.location.search);
  switch (type) {
    case sortTypeTitle:
      searchParams.set("sortType", "title");
      break;
    case sortTypeYear:
      searchParams.set("sortType", "year");
      break;
    case sortTypeId:
      searchParams.set("sortType", "id");
      break;
  }
  history.replaceState({}, '', window.location.pathname + '?' + searchParams.toString());
}


function splitBySort(movies: Array<Movie>): { [s: string]: Movie[]; } {
  switch (sortType) {
    case sortTypeYear:
      const sorted = movies.sort((a, b) => {
        const ay = Date.parse(a.released);
        const by = Date.parse(b.released);
        return ay - by;
      });
      return splitByYear(sorted);
    case sortTypeId:
      movies.sort((a, b) => a.id < b.id ? 1 : -1);
      return { "added": movies };
    default:
      return splitByTitle(movies.sort((a, b) => a.title.localeCompare(b.title)));
  }
}

function toggleEdit() {
  movieElements.forEach(element => {
    const div = element.querySelector(".d-none");
    if (!div) return;
    div.classList.remove("d-none");
    div.classList.add("d-flex");
  });
}

document.addEventListener('DOMContentLoaded', async () => {
  document.getElementById("myform")?.addEventListener("submit", submitMedia);

  listButtons.push(document.getElementById("movieButton"));
  listButtons.push(document.getElementById("gameButton"));
  listButtons.push(document.getElementById("seriesButton"));
  listButtons.forEach((button, index) => button?.addEventListener("click", () => changeType(index)));

  sortButtons.push(document.getElementById("titleButton"));
  sortButtons.push(document.getElementById("yearButton"));
  sortButtons.push(document.getElementById("idButton"));
  sortButtons.forEach((button, index) => button?.addEventListener("click", () => changeSort(index)));

  editButton = document.getElementById("editButton");
  editButton?.addEventListener("click", () => toggleEdit());

  loadState();
  loadPage();
});

async function loadPage() {

  listButtons.forEach(button => button?.classList.remove("active"));
  listButtons[listType]?.classList.add("active");

  try {
    const response = await fetch(getLink());
    const movies = await response.json();
    renderMedias(movies);
  } catch (err) {
    console.log(err);
  }
}


function removeMedia(evt: Event) {
  const password = document.getElementById("pass") as HTMLInputElement | null;
  if (!password) return;
  if (password.value == "") return;

  let elem = evt.target as HTMLElement | null;

  while (elem && !elem.classList.contains('media-element')) {
    elem = elem.parentElement;
  }

  if (!elem) return;
  const id = elem.id;

  fetch(getLink(), {
    body: JSON.stringify({ pass: password.value, code: id }),
    headers: { "Content-Type": "application/json" },
    method: "DELETE"
  })
    .then(async (response) => {

      if (response.status != 204) {
        console.log("error");
        console.log(response.body);
        return;
      }
      document.getElementById(id)?.remove();
    })
    .catch(err => {
      console.log(err);
    });
  password.value = "";
}

function onImgError(evt: Event) {
  const imgT = evt.target as HTMLImageElement;
  imgT.src = "/images/no_poster.jpg";
}

function renderMedias(unsorted_movies: Array<Movie>) {
  root = document.getElementById('root');
  if (!root) return;

  root.innerHTML = "";

  const splitMovies = splitBySort(unsorted_movies);

  let years;
  if (sortType == sortTypeTitle) {
    years = Object.keys(splitMovies).sort((a, b) => -b.localeCompare(a));
  } else {
    years = Object.keys(splitMovies).sort((a, b) => b.localeCompare(a));
  }


  root.appendChild(<MyHeader title={unsorted_movies.length} />);

  for (const letter of years) {

    const movies = splitMovies[letter];

    const header = <MyHeader title={letter} num={movies.length} />;
    root.appendChild(header);

    const row =
      <MediaContainer id={letter}>
        {movies.map(movie => {
          const med = <MediaElement webImg={movie.webImg} title={movie.title} released={movie.released} id={movie.code} fun={removeMedia} imageError={onImgError}></MediaElement>;
          movieElements.push(med);
          return med;
        })}
      </MediaContainer>;

    root.appendChild(row);
  }
}