// withHooks

import { EventHeader } from 'esoftplay/cache/event/header/import';
import { EventTap } from 'esoftplay/cache/event/tap/import';
import { LibCurl } from 'esoftplay/cache/lib/curl/import';
import { LibIcon } from 'esoftplay/cache/lib/icon/import';
import { LibLoading } from 'esoftplay/cache/lib/loading/import';
import { LibNavigation } from 'esoftplay/cache/lib/navigation/import';
import { LibObject } from 'esoftplay/cache/lib/object/import';
import { LibStyle } from 'esoftplay/cache/lib/style/import';
import { LibToastProperty } from 'esoftplay/cache/lib/toast/import';
import { LibUtils } from 'esoftplay/cache/lib/utils/import';
import esp from 'esoftplay/esp';
import useLazyState from 'esoftplay/lazy';
import React, { useEffect, useRef } from 'react';
import { Dimensions, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
import Animated, { useAnimatedProps, useSharedValue, withTiming } from 'react-native-reanimated';
import Svg, { G, Rect, Text as SVGText } from 'react-native-svg';

const AnimatedRect = Animated.createAnimatedComponent(Rect);
const AnimatedSVG = Animated.createAnimatedComponent(Svg);
const AnimatedSVGText = Animated.createAnimatedComponent(SVGText);


export default function m(props: any) {
  const { dataTicket, url } = LibNavigation.getArgsAll<any>(props)
  const qty = dataTicket?.qty
  let numRows = useRef(0)
  let numCols = useRef(0)
  let selectedSeat = useRef<any>(null).current

  const [seatNames, setSeatNames] = useLazyState<string[]>([])
  const [data, setData] = useLazyState<number[]>([])
  const [coordinates, setCoordinates] = useLazyState<string[]>([])
  const [selectedSeatData, setSelectedSeatData] = useLazyState<any>({})


  const squareSizeAnimated = useSharedValue(10)
  const marginAnimated = useSharedValue(squareSizeAnimated.value * 0.25)
  const boxSizeAnimated = useSharedValue(squareSizeAnimated.value + marginAnimated.value)
  const rBAnimated = useSharedValue(squareSizeAnimated.value * 0.1)

  function change(x: any) {
    const val = x * 0.25
    squareSizeAnimated.value = x
    marginAnimated.value = val
    boxSizeAnimated.value = x + val
    rBAnimated.value = x * 0.1

  }

  function plus() {
    let x = squareSizeAnimated.value * 3 / 2
    if (x <= 50) {
      change(x)
    }
  }

  function min() {
    let x = squareSizeAnimated.value * 2 / 3
    if (x >= 10)
      change(x)
  }

  function resetZoomAnim() {
    const square = (Dimensions.get('screen').width / numRows.current) * 0.75
    const margin = square * 0.25

    squareSizeAnimated.value = square
    marginAnimated.value = margin
    boxSizeAnimated.value = square + margin
    rBAnimated.value = square * 0.1
  }

  useEffect(() => {
    new LibCurl(url + '?' + LibUtils.objectToUrlParam({
      offset_row: 1, offset_column: 1
    }), {
      event_id: dataTicket.event_id,
      price_id: dataTicket?.selected_ticket?.price_id,
      ondate: dataTicket?.selected_ticket?.list?.ondate,
      compact: 4
    }, (res, msg) => {
      numRows.current = res.seat_row
      numCols.current = res.seat_column
      resetZoomAnim()
      setSeatNames(buildSeatNames(res.list.names, res.list.layout, setCoordinates))
      const sizes = res.list.statuses;
      const sizesArray: number[] = [];
      sizes?.split(",").forEach((size: string) => {
        if (size.includes('x')) {
          const [v, x] = size?.split("x");
          for (let i = 0; i < parseInt(v); i++) {
            sizesArray.push(parseInt(x));
          }
        } else {
          sizesArray.push(parseInt(size))
        }
      });
      setData(sizesArray)()
    })
  }, []);

  function toggleSeat(x: number, y: number) {
    const cx = Math.floor(x / boxSizeAnimated.value)
    const cy = Math.floor(y / boxSizeAnimated.value)
    const index = (((cy * numCols.current) + cx))
    const [_x, _y] = coordinates[index]?.split(":")

    selectedSeat = {
      x: _x,
      y: _y,
      index: index,
      name: seatNames[index]
    }
    const countQty = data.filter((x) => x == -1).length
    setData(LibObject.update(data, (old) => {
      let out = old;
      if (old == 0) {
        if (countQty >= qty) {
          LibToastProperty.show(esp.lang("event/seat_map", "max_seat", qty))
        } else {
          setSelectedSeatData(LibObject.set(selectedSeatData, selectedSeat)(selectedSeat.index))
          out = -1;
        }
      }
      if (old == -1) {
        out = 0;
        setSelectedSeatData(LibObject.set(selectedSeatData, () => null)(selectedSeat.index))
      }
      return out
    })(selectedSeat.index))()
  }

  if (data.length == 0) {
    return <LibLoading />
  }

  return (
    <View style={styles.container}>
      <EventHeader title={esp.lang("event/seat_map_test", "header_title")} />
      <View style={{ alignItems: 'center', flex: 1 }} >
        <ScrollView showsVerticalScrollIndicator style={{ marginTop: 12 }} >
          <View style={{ height: 30, marginHorizontal: 16, backgroundColor: LibStyle.colorPrimary, marginBottom: 20, borderRadius: 5, justifyContent: 'center', alignItems: 'center' }} >
            <Text style={{ color: 'white', fontWeight: 'bold' }} >{esp.lang("event/seat_map_test", "front")}</Text>
          </View>
          <ScrollView horizontal showsHorizontalScrollIndicator >
            <EventTap onCoordinateGet={toggleSeat}>
              <MatrixAnimated
                data={data}
                numRows={numRows}
                // mapWidth={numCols.current * boxSizeAnimated.value + (marginAnimated.value)}
                // mapHeight={numRows.current * boxSizeAnimated.value + (marginAnimated.value)}
                seatNames={seatNames}
                numCols={numCols}
                boxSize={boxSizeAnimated}
                margin={marginAnimated}
                squareSize={squareSizeAnimated}
                rB={rBAnimated}
              />
            </EventTap>
          </ScrollView>
        </ScrollView>
      </View>
      <View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
        <Pressable onPress={min} style={{ height: 40, width: 40, alignItems: 'center', justifyContent: 'center' }} >
          <LibIcon.SimpleLineIcons name='magnifier-remove' />
        </Pressable>
        <Pressable onPress={plus} style={{ height: 40, width: 40, alignItems: 'center', justifyContent: 'center' }} >
          <LibIcon.SimpleLineIcons name='magnifier-add' />
        </Pressable>
      </View>
    </View>
  );
}


function MatrixAnimated(props: any) {
  const { /* mapWidth, mapHeight, */ data, seatNames, numCols, numRows, boxSize, margin, squareSize, rB } = props
  let col = 0
  let row = 0

  const svgProps = useAnimatedProps(() => {
    return {
      width: withTiming(numCols.current * boxSize.value + (margin.value)),
      height: withTiming(numRows.current * boxSize.value + (margin.value)),
    }
  })

  return (
    <AnimatedSVG
      animatedProps={svgProps}
    // width={mapWidth} height={mapHeight}
    >
      {
        data.map((status: number, i: number) => {
          const c = seatNames[i]
          const color = status == -1 ? "#8EF67B" : "#f1f1f1"
          const colorDark = status == -1 ? "#15D71F" : "#aeaeae"
          if (i % (numCols.current) == 0) {
            col = i / (numCols.current)
          }
          row = i % numCols.current
          // const xSize = row * (boxSize.value) + margin.value
          // const ySize = col * (boxSize.value) + margin.value

          const duration = 1000

          const animatedPropsA = useAnimatedProps(() => {
            return {
              x: withTiming((row * (boxSize.value) + margin.value) + squareSize.value * 0.05, { duration }),
              y: withTiming((col * (boxSize.value) + margin.value), { duration }),
              rx: withTiming(rB.value, { duration }),
              ry: withTiming(rB.value, { duration }),
              width: withTiming(squareSize.value - (squareSize.value * 0.1), { duration }),
              height: withTiming(squareSize.value, { duration }),
            }
          })

          const animatedPropsB = useAnimatedProps(() => {
            return {
              x: withTiming((row * (boxSize.value) + margin.value), { duration }),
              y: withTiming((col * (boxSize.value) + margin.value) + squareSize.value * 0.8, { duration }),
              width: withTiming(squareSize.value, { duration }),
              height: withTiming(squareSize.value * 0.2, { duration }),
            }
          })

          const animatedPropsC = useAnimatedProps(() => {
            return {
              x: withTiming((row * (boxSize.value) + margin.value), { duration }),
              y: withTiming((col * (boxSize.value) + margin.value) + squareSize.value * 0.5, { duration }),
              width: withTiming(squareSize.value * 0.1, { duration }),
              height: withTiming(squareSize.value * 0.5, { duration }),
            }
          })

          const animatedPropsD = useAnimatedProps(() => {
            return {
              x: withTiming((row * (boxSize.value) + margin.value) + squareSize.value * 0.9, { duration }),
              y: withTiming((col * (boxSize.value) + margin.value) + squareSize.value * 0.5, { duration }),
              width: withTiming(squareSize.value * 0.1, { duration }),
              height: withTiming(squareSize.value * 0.5, { duration }),
            }
          })

          const animatedPropsE = useAnimatedProps(() => {
            return {
              x: withTiming([(row * (boxSize.value) + margin.value) + squareSize.value * 0.37], { duration }),
              y: withTiming([(col * (boxSize.value) + margin.value) + squareSize.value * 0.6], { duration }),
              fontSize: squareSize.value * 0.25,
            }
          })

          const animatedPropsF = useAnimatedProps(() => {
            return {
              x: withTiming((row * (boxSize.value) + margin.value), { duration }),
              y: withTiming((col * (boxSize.value) + margin.value), { duration }),
              rx: withTiming(rB.value, { duration }),
              ry: withTiming(rB.value, { duration }),
              width: withTiming(squareSize.value, { duration }),
              height: withTiming(squareSize.value, { duration }),
            }
          })

          if (status == 0 || status == -1) {
            return (
              <G key={row + ":" + col}>
                <AnimatedRect
                  animatedProps={animatedPropsA}
                  fill={color} />
                <AnimatedRect
                  rx={2}
                  ry={2}
                  animatedProps={animatedPropsB}
                  fill={colorDark} />
                <AnimatedRect
                  rx={2}
                  ry={2}
                  animatedProps={animatedPropsC}
                  fill={colorDark} />
                <AnimatedRect
                  rx={2}
                  ry={2}
                  animatedProps={animatedPropsD}
                  fill={colorDark} />
                <AnimatedSVGText
                  animatedProps={animatedPropsE}
                  fill="#060606"
                  textAnchor={"middle"}
                >{c}</AnimatedSVGText>
              </G>
            )
          } else {
            return (<AnimatedRect
              key={row + ":" + col}
              animatedProps={animatedPropsF}
              fill={getColorByStatus(status)} />)
          }
        })}
    </AnimatedSVG>
  )
}


function getColorByStatus(statuses: number) {
  const colors: any = {
    0: "#fff",
    1: "#9FA1A4",
    2: "#6B71E6",
    3: "#2EBBE8",
    4: "#FFA601",
    5: "#fff",
    6: "#FF4866",
  }
  return colors[statuses]
}

function buildSeatNames(input: string, { letter_axis, letter_position }: any, cb?: (coordinates: string[]) => void) {
  const output = [];
  let coordinates = []
  const sections = input?.split(",");


  function renderNames(letter_axis: string, letter_position: number, x: number, y: number) {
    coordinates.push(x + ':' + y)
    if (letter_position == 0) {
      if (letter_axis == 'x')
        output.push(toBase26(x) + y)
      else if (letter_axis == 'y') {
        output.push(toBase26(y) + x)
      }
    } else {
      if (letter_axis == 'x')
        output.push(y + toBase26(x))
      else if (letter_axis == 'y') {
        output.push(x + toBase26(y))
      }
    }
  }


  for (let a = 0; a < sections.length; a++) {
    if (sections[a].length == 0) {
      output.push("")
      coordinates.push('0:0')
    } else {
      const [x, y] = sections[a]?.split(":")
      if (!x.includes("-") && !y.includes('-')) {
        renderNames(letter_axis, letter_position, parseInt(x), parseInt(y))
      } else {
        const [xfrom, xto] = x?.split("-")
        const [yfrom, yto] = y?.split("-")
        if (xto) {
          if (parseInt(xfrom) <= parseInt(xto)) {
            for (let i1 = parseInt(xfrom); i1 <= parseInt(xto); i1++) {
              renderNames(letter_axis, letter_position, i1, parseInt(y))
            }
          } else {
            coordinates.push('0:0')
            output.push("")
          }
        } else if (yto) {
          if (parseInt(yfrom) <= parseInt(yto)) {
            for (let i = parseInt(yfrom); i <= parseInt(yto); i++) {
              renderNames(letter_axis, letter_position, i, parseInt(y))
            }
          } else {
            coordinates.push('0:0')
            output.push("")
          }
        }
      }
    }
  }

  if (cb) cb(coordinates)

  return output
}


// Function to convert a number to base26
function toBase26(num: number) {
  let result = "";

  while (num > 0) {
    let remainder = (num - 1) % 26;
    result = String.fromCharCode(65 + remainder) + result;
    num = Math.floor((num - 1) / 26);
  }

  return result;
}


const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});