import { Fill, Text, Icon, Stroke, Style, Circle } from 'ol/style';
import startIcon from '../../icons/flag-start-b-svgrepo-com-green.svg';
import finishIcon from '../../icons/flag-finish-b-o-svgrepo-com-red.svg';
import wptIcon from '../../icons/location-pin-svgrepo-com-green.svg';
import houseIcon from '../../icons/house-svgrepo-com.svg';
import houseFlatIcon from '../../icons/houseFlat-svgrepo-com.svg';
import campingIcon from '../../icons/camping-14-svgrepo-com.svg';
import farmPigIcon from '../../icons/farm-pig-svgrepo-com.svg';
import cheeseIcon from '../../icons/cheese-svgrepo-com.svg';
import trainIcon from '../../icons/train-svgrepo-com.svg';
import picnicIcon from '../../icons/picnic-svgrepo-com.svg';
import caveIcon from '../../icons/cave-entrance-svgrepo-com.svg';
import wptIconSel from '../../icons/location-pin-svgrepo-com-red.svg';
import { Feature } from 'ol';
import memoize from 'memoizee';
import { getState } from '../map';
import { Point } from 'ol/geom';

interface StyleParameters {
  type: string;
  isSelected: boolean;
}

const icons = {
  house: {
    src: houseIcon,
    scale: 1 / 15,
    opacity: 0.9,
    anchor: [0.5, 1],
  },
  houseFlat: {
    src: houseFlatIcon,
    scale: 1 / 15,
    opacity: 0.9,
    anchor: [0.5, 1],
  },
  camping: {
    src: campingIcon,
    scale: 2,
    opacity: 0.9,
    anchor: [0.5, 1],
  },
  farmPig: {
    src: farmPigIcon,
    scale: 1 / 12,
    opacity: 0.9,
    anchor: [0.5, 1],
  },
  cheese: {
    src: cheeseIcon,
    scale: 3 / 4,
    opacity: 0.9,
    anchor: [0.5, 1],
  },
  train: {
    src: trainIcon,
    scale: 1 / 10,
    opacity: 0.9,
    anchor: [0.5, 1],
  },
  picnic: {
    src: picnicIcon,
    scale: 1 / 15,
    opacity: 0.9,
    anchor: [0.5, 1],
  },
  cave: {
    src: caveIcon,
    scale: 1 / 7,
    opacity: 0.9,
    anchor: [0.5, 1],
  },
};

const wptIconObj = {
  src: wptIcon,
  scale: 0.1,
  opacity: 0.9,
  anchor: [0.5, 1],
};

const textStroke = new Stroke({
  color: '#fff',
  width: 3,
});
const textStrokeSel = new Stroke({
  color: 'blue',
  width: 2,
});
const textFill = new Fill({
  color: '#000',
});
const textFillSel = new Fill({
  color: 'red',
});

const trksegStroke = new Stroke({
  color: 'blue',
  width: 3,
});

const trksegStrokeSel = new Stroke({
  color: 'red',
  width: 3,
});

const rteStroke = new Stroke({
  color: 'green',
  width: 3,
});

const rteStrokeSel = new Stroke({
  color: 'red',
  width: 3,
});

const circleFill = new Fill({
  color: 'rgba(255,255,255,0.4)',
});

const circleStroke = new Stroke({
  color: '#3399CC',
  width: 1.25,
});

const circle = new Circle({
  fill: circleFill,
  stroke: circleStroke,
  radius: 5,
});

const replacer = (key: string, value: any) => {
  if (key === 'feature' && typeof value === 'object') {
    return { id: value.get('id'), rev: value.getRevision() };
  }
  return value;
};

const normalizer = (params: any) => {
  const key = JSON.stringify(params, replacer);
  //  console.log({ caller: 'getStyle / normalizer', key });
  return key;
};

const memoizeOptions = {
  length: 1,
  normalizer,
  max: 1024,
};

const zoom = () => Math.floor(getState().zoom);

const styles = {
  wpt: {
    getParameters: (feature: Feature) => {
      const minZoom = feature.get('extensions')?.['dyo:minZoom'];
      return {
        isSelected: feature.get('isSelected') ?? false,
        text: feature.get('name'),
        customIcon: icons[feature.get('sym') as keyof typeof icons],
        hidden: minZoom && zoom() < minZoom,
      };
    },
    getStyle: memoize((params: any) => {
      console.log({ caller: 'getStyle', params });
      const { isSelected, text, customIcon, hidden } = params;
      if (hidden) {
        return null;
      }
      const icon = customIcon ?? wptIconObj;
      return new Style({
        image: new Icon(icon),
        text: new Text({
          font: '16px Calibri,sans-serif',
          text: text,
          fill: isSelected ? textFillSel : textFill,
          stroke: isSelected ? textStrokeSel : textStroke,
          offsetY: -40,
        }),
      });
    }, memoizeOptions),
  },
  trkseg: {
    getParameters: (feature: Feature) => {
      return {
        isSelected: feature.get('isSelected') ?? false,
        feature: zoom() >= 15 ? feature : undefined,
      };
    },
    getStyle: memoize((params: any) => {
      console.log({ caller: 'getStyle', params });
      const { isSelected, feature } = params;
      const styles = [
        new Style({ stroke: isSelected ? trksegStrokeSel : trksegStroke }),
      ];
      if (feature) {
        const geometry = feature.getGeometry();
        geometry.forEachSegment((start: any, end: any) => {
          styles.push(new Style({ geometry: new Point(end), image: circle }));
        });
      }
      return styles;
    }, memoizeOptions),
  },
  rte: {
    getParameters: (feature: Feature) => {
      return {
        isSelected: feature.get('isSelected') ?? false,
      };
    },
    getStyle: memoize((params: any) => {
      console.log({ caller: 'getStyle', params });
      const { isSelected } = params;
      return new Style({ stroke: isSelected ? rteStrokeSel : rteStroke });
    }, memoizeOptions),
  },
};

export const style = (feature: Feature) => {
  const type = feature.get('type') as keyof typeof styles;
  console.log({ caller: 'style', type });
  const styleForType = styles[type];
  if (!styleForType) {
    return null;
  }
  const params = styles[type].getParameters(feature);
  const getStyle = styles[type].getStyle;
  return getStyle(params);
};

export default style;