import {
  View,
  Platform,
  TouchableOpacity,
  Text
} from 'react-native';
import React, { useEffect, useState, useRef, useMemo } from 'react';
import MapView, { UrlTile, Geojson } from 'react-native-maps';
import * as turf from '@turf/turf';
import * as FileSystem from 'expo-file-system';

import MenuIcon from '../../../../assets/icons/menu.svg';
import SearchIcon from '../../../../assets/icons/search.svg';
import RadarIcon from '../../../../assets/icons/radar.svg';
import LocationIcon from '../../../../assets/icons/location.svg';
import CloseSvg from '../../../../assets/icons/close.svg';

import regions from '../../../../assets/geojson/nm2022.json';
import dareRegions from '../../../../assets/geojson/mqp.json';

import NetInfo from "@react-native-community/netinfo";
import { getFirstDatabase, getSecondDatabase } from '../../../db';
import RegionPopup from '../../../components/RegionPopup';

import { BottomTabNavigationProp } from '@react-navigation/bottom-tabs';
import { styles } from './style';
import { findRegionInDataset, calculateMapRegion } from '../../../utils/mapHelpers';
import { getData } from '../../../modules/map/regionData';

const tilesBaseURL = 'https://maps.nomadmania.com/tiles_osm';
const localTileDir = `${FileSystem.cacheDirectory}tiles`;

const gridUrl = 'https://maps.nomadmania.com/tiles_nm/grid';
const localGridDir = `${FileSystem.cacheDirectory}tiles/grid`;

const visitedTiles = 'https://maps.nomadmania.com/tiles_nm/user_visited/51363';
const localVisitedDir = `${FileSystem.cacheDirectory}tiles/user_visited`;

const dareTiles = 'https://maps.nomadmania.com/tiles_nm/regions_mqp';
const localDareDir = `${FileSystem.cacheDirectory}tiles/regions_mqp`;

interface Region {
  id: number;
  name: string;
  region_photos: string;
  visitors_count: number;
}

interface MapScreenProps {
  navigation: BottomTabNavigationProp<any>;
}

const MapScreen: React.FC<MapScreenProps> = ({ navigation }) => {
  const mapRef = useRef<MapView>(null);

  const [isConnected, setIsConnected] = useState<boolean | null>(true);
  const [selectedRegion, setSelectedRegion] = useState(null);
  const [popupVisible, setPopupVisible] = useState<boolean | null>(false);
  const [regionData, setRegionData] = useState<Region | null>(null);
  const [userAvatars, setUserAvatars] = useState<string[]>([]);

  useEffect(() => {
    navigation.setOptions({
      tabBarStyle: {
        display: popupVisible ? 'none' : 'flex',
        position: 'absolute',
        ...Platform.select({
          android: {
            height: 58,
          },
        }),
      }
    });
  }, [popupVisible, navigation]);

  const handleRegionData = (regionData: Region, avatars: string[]) => {
    setRegionData(regionData);
    setUserAvatars(avatars);
  };

  const handleMapPress = async (event: { nativeEvent: { coordinate: { latitude: any; longitude: any; }; }; }) => {
    const { latitude, longitude } = event.nativeEvent.coordinate;
    const point = turf.point([longitude, latitude]);
    setUserAvatars([]);

    let db = getSecondDatabase();
    let tableName = 'places';

    let foundRegion = findRegionInDataset(dareRegions, point);

    if (!foundRegion) {
      foundRegion = findRegionInDataset(regions, point);
      db = getFirstDatabase();
      tableName = 'regions';
    }

    if (foundRegion) {
      const id = foundRegion.properties?.id;

      setSelectedRegion({
        type: 'FeatureCollection',
        features: [{
          geometry: foundRegion.geometry,
          properties: {
            ...foundRegion.properties,
            fill: "rgba(57, 115, 172, 0.2)",
            stroke: "#3973AC",
          },
          type: 'Feature',
        }]
      });

      await getData(db, id, tableName, handleRegionData)
      .then(() => {
        setPopupVisible(true);
      })
      .catch(error => {
        console.error("Error fetching data", error);
      });

      const bounds = turf.bbox(foundRegion);
      const region = calculateMapRegion(bounds);

      mapRef.current?.animateToRegion(region, 1000);
    } else {
      handleClosePopup();
    }
  };

  useEffect(() => {
    const unsubscribe = NetInfo.addEventListener(state => {
      setIsConnected(state.isConnected);
    });
  
    return () => unsubscribe();
  }, []);

  const renderMapTiles = (
    url: string,
    cacheDir: string,
    zIndex: number,
    opacity = 1
  ) => (
    <UrlTile
      urlTemplate={`${url}/{z}/{x}/{y}`}
      maximumZ={15}
      maximumNativeZ={13}
      tileCachePath={`${cacheDir}`}
      shouldReplaceMapContent
      minimumZ={0}
      offlineMode={!isConnected}
      opacity={opacity}
      zIndex={zIndex}
    />
  );

  function renderGeoJSON() {
    if (!selectedRegion) return null;

    return (
        <Geojson
          geojson={selectedRegion}
          fillColor="rgba(57, 115, 172, 0.2)"
          strokeColor="#3973ac"
          strokeWidth={Platform.OS == 'android' ? 3 : 2}
          zIndex={3}
        />
    );
  };

  const handleClosePopup = () => {
    setPopupVisible(false);
    setSelectedRegion(null);
  }

  const renderedGeoJSON = useMemo(() => renderGeoJSON(), [selectedRegion]);

  return (
    <View style={styles.container}>
      <MapView
        ref={mapRef}
        showsMyLocationButton={false}
        showsCompass={false}
        zoomControlEnabled={false}
        onPress={handleMapPress}
        style={styles.map}
        mapType={Platform.OS == 'android' ? 'none' : 'standard'}
        offlineMode={!isConnected}
        maxZoomLevel={15}
        minZoomLevel={0}
      >
        {renderedGeoJSON}
        {renderMapTiles(tilesBaseURL, localTileDir, 1)}
        {renderMapTiles(gridUrl, localGridDir, 2)}
        {renderMapTiles(visitedTiles, localVisitedDir, 2, 0.5)}
        {renderMapTiles(dareTiles, localDareDir, 2, 0.5)}
      </MapView>

      {popupVisible && regionData ? (
        <>
          <TouchableOpacity
            style={[ styles.cornerButton, styles.topLeftButton, styles.closeLeftButton ]}
            onPress={handleClosePopup}
          >
            <CloseSvg
              fill="white"
              width={13}
              height={13}
            />
            <Text style={styles.textClose}>Close</Text>
          </TouchableOpacity>

          <TouchableOpacity style={[ styles.cornerButton, styles.topRightButton, styles.bottomButton ]}>
            <LocationIcon />
          </TouchableOpacity>

          <RegionPopup 
            region={regionData}
            userAvatars={userAvatars}
            onMarkVisited={() => console.log('Mark as visited')} 
          />
        </>
      ) : (
        <>
          <TouchableOpacity style={[styles.cornerButton, styles.topLeftButton]}>
            <MenuIcon />
          </TouchableOpacity>

          <TouchableOpacity style={[styles.cornerButton, styles.topRightButton]}>
            <SearchIcon />
          </TouchableOpacity>

          <TouchableOpacity style={[styles.cornerButton, styles.bottomButton, styles.bottomLeftButton]}>
            <RadarIcon />
          </TouchableOpacity>

          <TouchableOpacity style={[styles.cornerButton, styles.bottomButton, styles.bottomRightButton]}>
            <LocationIcon />
          </TouchableOpacity>
        </>
      )}
    </View>
  );
}

export default MapScreen;
