import React, { Fragment, useEffect, useState } from 'react';
import './App.css';
import GalleryCard from './GalleryCard';

const defaultSet: any = (size: number) => {
  const newSet = new Set<number>();
  for (var i: number = 1; i <= size; i++) newSet.add(i);
  return newSet;
}


const stateToString: (s: Set<number>) => (string) = (s: Set<number>) => {
  const numbers: Array<number> = Array.from(s).sort((a, b) => a - b);
  var cur = -1;
  var length = 1;
  var out: Array<string> = [];
  const output: (cur: number, length: number) => any = (cur, length) => {
    var start = cur;
    var end = cur + length - 1;
    if (length === 1) {
      out.push(start.toString());
    } else if (length === 2) {
      out.push(start.toString());
      out.push(end.toString());
    } else {
      out.push(`${start}-${end}`);
    }
  };
  for (var i: number = 0; i < numbers.length; i++) {
    if (cur === -1) {
      cur = numbers[i];
    } else {
      if (numbers[i - 1] === numbers[i] - 1) {
        length++;
      } else {
        output(cur, length);
        cur = numbers[i];
        length = 1;
      }
    }
    if (i === numbers.length - 1) {
      output(cur, length);
    }
  }
  return out.join(",");
};

const stringToState: (s: string) => (Set<number>) = (s: string) => {
  var out: Set<number> = new Set<number>();
  const REGEX = "(?<short>^\\d+$)|(?<long>^(?<long1>\\d+)-(?<long2>\\d+)$)";
  s.split(",").forEach((str: string) => {
    var groups = str.match(REGEX)?.groups;
    if (groups?.short) {
      var short: number = parseInt(groups.short);
      out.add(short);
    } else if (groups?.long1 && groups?.long2) {
      var long1: number = parseInt(groups.long1);
      var long2: number = parseInt(groups.long2);
      for (var i = long1; i <= long2; i++) out.add(i);
    }
  });
  return out;
};

const loadSet: (() => Set<number>) = () => {
  var href: string = document.location.href;
  var afterHref: string = href === href.split("#")[0] ? "" : href.split("#")[1];
  var numbers = stringToState(afterHref);
  return numbers;
};

const storeSet: ((set: Set<number>) => void) = (collection) => {

  var href = document.location.href;
  var pureHref: string = href.split("#")[0];
  var newstate = stateToString(collection);
  document.location.href = `${pureHref}#${newstate}`;
};

const Gallery: React.FC<{ size: number }> = ({ size }) => {
  const originalSet: Set<number> = defaultSet(size);
  const [collection, setCollection] = useState(loadSet());

  function addToCollection(toRemove: number) {
    return setCollection(previousState => new Set<number>([...Array.from(previousState), toRemove]));
  }

  useEffect(() => storeSet(collection));

  const clickHandler: ((value: number) => ((eve: React.MouseEvent) => any)) = (value) => {
    return (event: React.MouseEvent) => {
      var element = event.currentTarget;
      element.setAttribute("style", "");
      var opacity = 1.0;  // initial opacity
      var timer = setInterval(function () {
        if (opacity <= 0.1) {
          clearInterval(timer);
          addToCollection(value);
        } else {
          element.setAttribute("style", `opacity: ${opacity};`);
        }
        opacity *= 0.9;
      }, 7);
    };
  };

  return (
    <Fragment>
      {Array.from(originalSet).filter(element => !collection.has(element)).map((value, key, theset) =>
        <GalleryCard id={value} key={value} clickHandler={clickHandler(value)} />
      )}
    </Fragment>)
};

export default Gallery;