import React, { useState, useEffect } from 'react';
import Container from '../components/container';
import { useRoute } from '@react-navigation/native';
import { customStyles, GetPageTheme } from "../styles/Global";
import { Image, View, Text, ScrollView, TouchableOpacity, Platform, StyleSheet } from 'react-native';
import { connect } from 'react-redux';
import { mapStateToProps, mapDispatchToProps } from '../reducers/contextProvider';
import { notify } from '../components/notify';
import moment from 'moment';
import { restore_ImageWithMetaData, UploadData2, UploadFormData } from '../controller/functions';
import { CoverageImagePath, db, URL_IMAGE } from '../constants/constants';
import CustomHeader from '../components/customHeader';
import { Entypo } from '../components/icons';
import CustomLoader from '../components/CustomLoader';
import LinearGradient from 'react-native-linear-gradient';
import MapView, { Marker, AnimatedRegion, PROVIDER_GOOGLE, Polyline } from 'react-native-maps';
import { _checkLocationPermission } from '../components/geolocation';
import Geolocation from 'react-native-geolocation-service';
import { useRef } from 'react';
import GradientButton from '../components/gradientButton';
import * as RNFS from 'react-native-fs';
import { AppTables } from '../constants/tableConstants';
import { getMethodName, METHODS } from '../constants/methodNames';
import CustomCamera from '../components/Camera';

function GeoTag(props) {
  const route = useRoute();
  const ST = props.StaticText || {};
  // get all theme styles acc to current theme set 
  const PageTheme = GetPageTheme(props.DarkMode, route.name);
  const customStyle = customStyles(props.DarkMode, route.name);
  const [processing, setProcessing] = useState(false);
  const [storeData, setStoreData] = useState({});
  const [StoreImage, setStoreImage] = useState('');
  const [StoreImgPath, setStoreImgPath] = useState('');
  const [currentLocation, setCurrentLocation] = useState({});
  const [markerCoordinate, setMarkerCoordinate] = useState();
  const [markerPos, setMarkerPos] = useState({});
  const [markerTitle, setMarkerTitle] = useState('');
  const [markerPlaceText, setMarkerPlaceText] = useState('');
  const [loaderTitle, setLoaderTitle] = useState();
  const [isAdhocScreen, setIsAdhocScreen] = useState(false);
  const [isBeatPlan, setIsBeatPlan] = useState(false);
  const [isDistributor, setIsDistributor] = useState(false);
  const [showCamera, setShowCamera] = useState(false);
  const [isNonMerchan, setIsNonMerchan] = useState(false);
  const [isNonProg, setIsNonProg] = useState(false);
  const [isStoreSearch, SetIsStoreSearch] = useState(false);

  const MyMap = useRef(null);
  const MyMarker = useRef(null);
  const isCancelled = useRef(false);
  const d1 = new Date();
  const d2 = moment(d1).format('MM/DD/YYYY');

  useEffect(() => {
    setLoaderTitle(ST.Loading + '...')
    _getCurrentLocation();
    let params = props.route.params ? props.route.params : {};
    let storeData1 = params.storeData || {};
    let isAdhoc = params.isAdhoc || false;
    let isBeat = params.isBeat != null ? params.isBeat : false;
    let isDistributor1 = params.isDistributor != null ? params.isDistributor : false;
    let isNonMerchan = params.isNonMerchans != null ? params.isNonMerchans : false;
    let isNonProgam = params.isNonProgs != null ? params.isNonProgs : false;
    let isStoreSearch = params.isStoreSearch != null ? params.isStoreSearch : false;
    setIsAdhocScreen(isAdhoc);
    setIsBeatPlan(isBeat);
    setIsNonMerchan(isNonMerchan)
    setIsNonProg(isNonProgam)
    SetIsStoreSearch(isStoreSearch)
    setIsDistributor(isDistributor1);
    setStoreData(storeData1);

    const unsubscribe = props.navigation.addListener('beforeRemove', onBeforeRemove);

    return function cleanup() {
      isCancelled.current = true;
      return unsubscribe;
    };
  }, []);

  useEffect(() => {
    const unsubscribe = props.navigation.addListener('beforeRemove', onBeforeRemove);
    return unsubscribe;
  }, [showCamera]);

  function onBeforeRemove(e) {
    if (showCamera == true) {
      e.preventDefault();
      setShowCamera(false);
    }
    else {
      return;
    }
  }

  async function _getCurrentLocation() {
    const hasPermission = await _checkLocationPermission();
    if (hasPermission == true) {
      Geolocation.getCurrentPosition(
        async (position) => {
          let latitude = position.coords.latitude;
          let longitude = position.coords.longitude;
          latitude = parseFloat(parseFloat(latitude).toFixed(8).replace("-e", ""));
          longitude = parseFloat(parseFloat(longitude).toFixed(8).replace("-e", ""));

          let loc = { lat: latitude, lng: longitude };
          setMarkerPos(loc);
          setMarkerCoordinate(new AnimatedRegion({ latitude: loc.lat, longitude: loc.lng }));
          setMarkerTitle('Current Location');
          setMarkerPlaceText(`${loc.lat}, ${loc.lng}`)
          setCurrentLocation(loc);
        },
        (error) => {
          notify(ST.Cannotgetuserposition);
        },
        { enableHighAccuracy: true, distanceFilter: 0, interval: 1000, fastestInterval: 2000 }
      );
    }
    else {
      notify(ST.Pleaseallowlocationpermission);
    }
  }

  async function _getLocationOnUpload() {
    const hasPermission = await _checkLocationPermission();
    if (hasPermission == true) {
      Geolocation.getCurrentPosition(
        async (position) => {
          let latitude = position.coords.latitude;
          let longitude = position.coords.longitude;
          latitude = parseFloat(parseFloat(latitude).toFixed(8).replace("-e", ""));
          longitude = parseFloat(parseFloat(longitude).toFixed(8).replace("-e", ""));

          let loc = { lat: latitude, lng: longitude };
          setMarkerPos(loc);
          setMarkerCoordinate(new AnimatedRegion({ latitude: loc.lat, longitude: loc.lng }));
          setMarkerTitle('Current Location');
          setMarkerPlaceText(`${loc.lat}, ${loc.lng}`)
          setCurrentLocation(loc);
          await InsertGeoTag(loc);
        },
        (error) => {
          notify(ST.Cannotgetuserposition);
        },
        { enableHighAccuracy: true, distanceFilter: 0, interval: 1000, fastestInterval: 2000 }
      );
    }
    else {
      notify(ST.Pleaseallowlocationpermission);
    }
  }

  async function submitGeoTag() {
    if (validate()) {
      setLoaderTitle(ST.UploadingData + '...');
      setProcessing(true);
      _getLocationOnUpload();

    }
  }


  async function InsertGeoTag(loc = {}) {
    try {

      await db.transaction(async function (txn) {
        let { StoreId } = storeData;
        let { lat, lng } = loc;
        console.log('geotag lat:', lat, 'lng:', lng);
        let status = 'N';
        let tb1 = isDistributor ? AppTables.DB_GEOTAG : AppTables.GEOTAG;
        let values = ` ('${StoreId}','${lat}','${lng}','${status}','${status}','${StoreImgPath}','${d2}') `;
        let q = `INSERT INTO ${tb1}(STORE_ID,LATITUDE,LONGITUDE,GEO_TAG,STATUS,FRONT_IMAGE,ADDED_DATE) VALUES ${values} `;

        await txn.executeSql(`Delete from ${tb1} where STORE_ID='${StoreId}' and ADDED_DATE='${d2}'`, [], async function (txn2, txnres2) {
          console.log('old geotag removed');
          await txn.executeSql(q, [], async function (txn2, txnres3) {
            console.log('geotag  added');
            uploadGeoTagData(loc);
          }, function (Etxn, txnerr) { console.log(txnerr); });

        }, function (Etxn, txnerr) { console.log(txnerr); });

      });

    }
    catch (e) {
      console.log(e); setProcessing(false);
    }
  }

  async function uploadGeoTagData(loc = {}) {
    let { lat, lng } = loc;
    let geotag_obj = {};

    if (isDistributor) {
      geotag_obj["DISTRIBUTOR_ID"] = storeData.StoreId;
    } else {
      geotag_obj["STORE_ID"] = storeData.StoreId;
    }
    geotag_obj["VISIT_DATE"] = d2,
      geotag_obj["LATITUDE"] = lat,
      geotag_obj["LONGITUDE"] = lng,
      geotag_obj["FRONT_IMAGE"] = StoreImage;

    let allGeoTags = [geotag_obj];
    let data = {
      "MID": "0",
      "JsonData": JSON.stringify(allGeoTags),
      "UserId": (props.UserId || ''),
    };

    if (isDistributor) {
      data["Keys"] = "DB_GeoTag";
    } else {
      data["Keys"] = "GeoTag";
    }

    const url = props.baseurl + getMethodName(METHODS.UPLOADJSON_METHOD);
    const url1 = (props.imageUploadUrl || URL_IMAGE) + getMethodName(METHODS.UPLOADIMAGES_METHOD);
    console.log(url, data);

    await UploadData2(url, data)
      .then(async (res) => {
        console.log(res);

        if (res.UploadJsonResult && res.UploadJsonResult.includes('Success')) {
          await UpdateGeoTagStatus(loc);
          // Upload Image 
          // await UploadFormData(url1,data1)
          // .then(async(res1)=>{         
          //   console.log('res1:',res1);      
          //   if(res1.includes('Success')){
          //     console.log('image uploaded');
          //     RNFS.unlink(StoreImgPath);
          //   }       
          // })
          // .catch((err)=>{
          //   console.log(err);
          // });
        }
        else {
          setProcessing(false);
          notify(ST.Cannotuploadgeotag)
        }
      })
      .catch((err) => {
        console.log(err); setProcessing(false);
      });

  }

  function exit(storeData1 = {}) {
    notify(ST.GeoTagDataUploadedSuccessfully, 'LONG');
    setProcessing(false);
    if (isDistributor) {
      props.navigation.replace('DistributorCheckIn', { storeData: storeData1, 'isAdhoc': isAdhocScreen, 'isBeat': isBeatPlan, 'isDistributor': isDistributor })
    }
    else {
      props.navigation.replace('StoreCheckin', { storeData: storeData1, 'isAdhoc': isAdhocScreen, 'isBeat': isBeatPlan, 'isDistributor': isDistributor, 'isNonMerchans': isNonMerchan, isNonProgs: isNonProg, isStoreSearch: isStoreSearch })
    }
  }

  async function UpdateGeoTagStatus(loc = {}) {
    try {
      await db.transaction(async function (txn) {
        let { StoreId } = storeData;
        let { lat, lng } = loc;
        let status = 'Y';
        let tb1 = isDistributor ? AppTables.DB_GEOTAG : AppTables.GEOTAG;
        let JcpType = isDistributor == true ? "Master_Distributor" : (isBeatPlan == true ? 'JourneyPlan_RouteWise' : (isAdhocScreen == true ? 'Adhoc_JourneyPlan' : (isNonMerchan == true ? 'NonMerchandising_JourneyPlan' : isNonProg == true ? 'NonProgram_JourneyPlan' : isStoreSearch == true ? 'StoreSearch_JourneyPlan' : 'Mapping_JourneyPlan')));
        let q = `Update ${tb1} set GEO_TAG='${status}',STATUS='${status}'  where STORE_ID='${StoreId}' and ADDED_DATE='${d2}'`;
        await txn.executeSql(q, [], async function (txn2, txnres2) {
          console.log('geotag update');

          let q2 = `Update ${JcpType} set GeoTag='${status}',Latitude='${lat}',Longitude='${lng}'  where ${isDistributor ? 'DistributorId' : 'StoreId'}='${StoreId}'`;
          await txn.executeSql(q2, [], async function (txn2, txnres2) {
            console.log('geotag updated in store');
            // update geotag locally
            let stored_new = storeData;
            stored_new['GeoTag'] = 'Y';
            stored_new['Latitude'] = lat;
            stored_new['Longitude'] = lng;
            setStoreData(stored_new);
            exit(stored_new);
          }, function (Etxn, txnerr) { console.log(txnerr); notify(ST.Geotaguploadedbutcannotupdategeotagstatus, 'LONG'); setProcessing(false); });

        }, function (Etxn, txnerr) { console.log(txnerr); notify(ST.Geotaguploadedbutcannotupdategeotagstatus, 'LONG'); setProcessing(false); });
      });
    }
    catch (e) {
      console.log(e);
      notify(ST.Geotaguploadedbutcannotupdategeotagstatus, 'LONG'); setProcessing(false);
    }
  }

  function validate() {
    if (StoreImage == '' || StoreImage == null) {
      notify((isDistributor ? 'Please click distributor front image' : ST.Pleaseclickstorefrontimage), 'SHORT');
      return false;
    }
    return true;
  }

  async function getImage(imgdata) {
    if (typeof imgdata == 'object' && imgdata.errorCode == 'camera_unavailable') {
      notify(ST.Cameraunavailable);
    }
    else if (typeof imgdata == 'object' && imgdata.uri != null) {
      const img = imgdata;
      const imgurl = img.uri, imgWidth = img.width, imgHeight = img.ExtendedHeight;
      let isImgFromGallery = img.fromGallery != null ? img.fromGallery : false;
      let picture_clickedd = isImgFromGallery == true ? img.datetime : new Date();
      let picture_clicked_time = moment(picture_clickedd).format('MM-DD-YYYY HH:mm:ss')
      let picture_clicked_time_for_pic_name = moment(picture_clickedd).format('MMDDYYYY_HHmmss')
      console.log("time", picture_clicked_time);
      console.log("time1", picture_clicked_time_for_pic_name);
      let calculate_tym_date_for_filename = picture_clicked_time_for_pic_name;
      let calculate_tym_date_over_img = picture_clicked_time;

      const mark_text1 = calculate_tym_date_over_img;
      let mark_text2 = '';
      if (isDistributor) {
        mark_text2 = 'Distributor Name:' + storeData.StoreName + ' | Distributor Id:' + storeData.StoreId + ' | User Id:' + storeData.EmpId + ' | Image Type: DB Geo Tag' + ' | Date:' + calculate_tym_date_over_img;
      }
      else {
        mark_text2 = 'Store Name:' + storeData.StoreName + ' | Store Id:' + storeData.StoreId + ' | User Id:' + storeData.EmpId + ' | Image Type: Geo Tag' + ' | Date:' + calculate_tym_date_over_img;
      }

      let filename = '';
      if (isDistributor) {
        filename = storeData.StoreId + '_' + storeData.EmpId + '_DBGeoTag-' + calculate_tym_date_for_filename + '.jpg';
      }
      else {
        filename = storeData.StoreId + '_' + storeData.EmpId + '_GeoTag-' + calculate_tym_date_for_filename + '.jpg';
      }

      setStoreImage(filename);
      let imagePath = `${CoverageImagePath}${filename}`;
      await RNFS.copyFile(imgurl, imagePath)
        .then(async (resn) => {
          // render data with clicked image
          let uri = 'file://' + imagePath;
          console.log('image marker', uri);
          setStoreImgPath(uri);
          // add metdata then resize image and restored back to the imagePath
          let restore_data = { "destFilePath": imagePath, "imgurl": imgurl, imgWidth, imgHeight, mark_text1, mark_text2 }
          let is_restored = await restore_ImageWithMetaData(restore_data, imgdata);
          console.log("image restored:", is_restored);
        })
        .catch(err => {
          console.log(ST.Errorimagefilewritefailed + '!!!');
          console.log(err.message, err.code);
        });
    }
  }

  function getImageBottomText() {
    if (isDistributor) {
      return 'Distributor Name:' + storeData.StoreName + ' | Distributor Id:' + storeData.StoreId + ' | User Id:' + storeData.EmpId + ' | Image Type: DB Geo Tag';
    }
    else {
      return 'Store Name:' + storeData.StoreName + ' | Store Id:' + storeData.StoreId + ' | User Id:' + storeData.EmpId + ' | Image Type: Geo Tag';
    }
  }

  async function openCamera() {
    setShowCamera(true);
  }


  function moveMarkerToPos(e) {
    let coords = e.nativeEvent.coordinate;
    console.log('moveMarkerToPos', coords)
    animateCamera(coords);
    animateMarkerToRegion(coords);
    setMarkerInfo(coords);
    let loc = { lat: coords.latitude, lng: coords.longitude };
    setMarkerPos(loc);
  }

  function animateMarkerToRegion(coords) {
    const newCoordinate = coords;
    const new_animated_coords = new AnimatedRegion({ latitude: coords.latitude, longitude: coords.longitude });
    if (Platform.OS === 'android') {
      if (MyMarker) {
        MyMarker.current.animateMarkerToCoordinate(newCoordinate, 1000);
      }
    } else {
      // `useNativeDriver` defaults to false if not passed explicitly
      markerCoordinate.timing({ ...newCoordinate, useNativeDriver: false, duration: 1000 }).start();
    }
    setTimeout(() => { setMarkerCoordinate(new_animated_coords); }, 1000);

  }

  async function setMarkerInfo(coords) {
    if (MyMap.current != null) {
      MyMap.current.addressForCoordinate(coords)
        .then((res) => {
          console.log('res:', res);
          let title = res.name;
          let placeText = `${res.subLocality}, ${res.locality}, ${res.administrativeArea} ${res.postalCode}`;
          setMarkerTitle(title);
          setMarkerPlaceText(placeText);

        })
    }
  }

  async function animateCamera(coords) {
    if (MyMap.current != null) {
      const camera = await MyMap.current.getCamera();
      // camera.heading = 90;
      // camera.pitch = 45;
      // camera.altitude = 1000;
      // camera.zoom = 1000;
      camera.center.latitude = coords.latitude;
      camera.center.longitude = coords.longitude;
      MyMap.current.animateCamera(camera, { duration: 2000 });
    }
  }

function _renderMap() {
    const lat = currentLocation.lat ? currentLocation.lat : 28.579660;
    const lng = currentLocation.lng ? currentLocation.lng : 77.321110;

    if (currentLocation.lat != null) {
      return (
        <View style={[customStyle.mapContainer]}>
          <View style={[customStyle.mapCard]}>
            {/* MAP */}
            <MapView
              ref={MyMap}
              provider={PROVIDER_GOOGLE}
              style={StyleSheet.absoluteFillObject}
              showsUserLocation={true}
              zoomEnabled={true}
              // 🔥 ANDROID 9 FIX (MOST IMPORTANT)
              renderToHardwareTextureAndroid={true}
              initialCamera={{
                center: { latitude: lat, longitude: lng },
                pitch: 7,
                heading: 7,
                altitude: 100,
                zoom: 19,
              }}
            >
              <Marker.Animated
                ref={MyMarker}
                coordinate={markerCoordinate}
                pinColor={'#ff78b6'}
                title={markerTitle}
                description={markerPlaceText}
              />
              <Polyline
                coordinates={[
                  { latitude: currentLocation.lat, longitude: currentLocation.lng },
                  { latitude: markerPos.lat, longitude: markerPos.lng }
                ]}
                strokeColor={'#00a4eb'}
                strokeWidth={4}
              />
            </MapView>
          </View>
          {/* CAMERA BUTTON OVERLAY (NOW ABOVE MAP) */}
          <View style={[customStyle.cameraOverlay]}>
            {_render_captureImage()}
          </View>
        </View>
      );
    }

    return <View />;
  }

  function _render_captureImage() {
    const isImageAvlbl = StoreImage != '' && StoreImage != null && StoreImgPath != '' && StoreImgPath != null;

    return (
      <View style={[customStyle.gtag_sImageWrap,{ bottom: -85 }]}>
        <View style={customStyle.gtag_sImagelbl}>
          <View style={customStyle.gtag_sImage_View}>
            {isImageAvlbl && <Image style={customStyle.gTag_Image} source={{ uri: StoreImgPath }} />}
            {!isImageAvlbl && <Image style={customStyle.gTag_Image} source={require('../assets/image/greybg.jpg')} />}
          </View>
          <TouchableOpacity style={customStyle.gTag_sImageBtn} onPress={() => { openCamera() }}>
            {<Entypo size={20} color={'#fff'} name='camera' />}
          </TouchableOpacity>
          <Text style={customStyle.gtag_sImagelblText}>{(isDistributor ? 'Click distributor front image' : ST.ClickStoreFrontImage)}</Text>
        </View>

      </View>
    );
  }

  return (
    <Container {...props} pt={0} avoidSafeArea={(Platform.OS == 'ios' ? true : false)}>
      {processing && <CustomLoader fullHeight={true} title={loaderTitle} />}
      <CustomHeader {...props} showaddstore={true} title={ST.Geotag} />
      <CustomCamera cameraType={'back'} BottomText={getImageBottomText()} enableGallerForScreen={props.CheckInCameraGallery} onImageCaptured={(imgData) => { setShowCamera(false); getImage(imgData) }} showCamera={showCamera} onHideCamera={() => { setShowCamera(false); }} />

      <LinearGradient colors={[PageTheme.$gradient1, PageTheme.$primary_color]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={customStyle.roundScrollWrapper}>
        <View style={[customStyle.pageContentWrapper]}>
          {Object.keys(storeData).length > 0 &&
            <ScrollView contentContainerStyle={customStyle.geotag_scroll} style={{}}>

              <View style={[customStyle.storel, customStyle.storeInfo_wrap]}>

                <View style={customStyle.storel_card_outer}>
                  <View style={customStyle.storel_card}>
                    <View style={customStyle.storel_card_content}>
                      <Text style={customStyle.storel_card_title}>{storeData.StoreName}</Text>
                    </View>
                  </View>
                  <View style={customStyle.storel_details}>
                    <View style={customStyle.storel_code}>
                      <View style={[customStyle.storel_codeCon, customStyle.storel_codeBorder]}>
                        <Text style={customStyle.storel_codeLbl}>{ST.StoreId + ':'}</Text>
                        <Text style={customStyle.storel_codeText}>{storeData.StoreId}</Text>
                      </View>
                      <View style={[customStyle.storel_codeCon]}>
                        <Text style={customStyle.storel_codeLbl}>{ST.StoreCode + ':'}</Text>
                        <Text style={customStyle.storel_codeText}>{storeData.StoreCode}</Text>
                      </View>
                    </View>
                    <View style={customStyle.storel_code}>
                      <View style={[customStyle.storel_codeCon]}>
                        <Text style={customStyle.storel_codeLbl}>{ST.Address + ':'}</Text>
                        <Text style={customStyle.storel_codeText}>{storeData.Address}</Text>
                      </View>
                    </View>
                  </View>
                </View>

              </View>
              {
                _renderMap()
              }
              <View style={customStyle.gTag_btnWrap}>
                <GradientButton {...props} title={ST.UploadGeotag} colors={[PageTheme.$red_light100, PageTheme.$red, PageTheme.$red]} style={{ shadowColor: PageTheme.$red }} onPress={() => { submitGeoTag() }} />
              </View>
            </ScrollView>
          }
        </View>
      </LinearGradient>

    </Container>
  );
}



export default connect(mapStateToProps, mapDispatchToProps)(GeoTag);