import { useMutation } from '@apollo/react-hooks'
import { Ionicons } from '@expo/vector-icons'
import { useNavigation, useRoute, useTheme } from '@react-navigation/native'
import * as Location from 'expo-location'
import gql from 'graphql-tag'
import { keys } from 'lodash'
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'
import {
  Image,
  KeyboardAvoidingView,
  Platform,
  ScrollView,
  TouchableOpacity,
  View
} from 'react-native'
import MapView, {
  Marker,
  PROVIDER_DEFAULT,
  PROVIDER_GOOGLE
} from 'react-native-maps'
import { FilledTextField } from 'react-native-material-textfield'
import i18n from '../../../i18n'
import { createAddress } from '../../apollo/server'
import {
  FlashMessage,
  Spinner,
  TextDefault,
  WrapperView
} from '../../components'
import { alignment } from '../../utils/alignment'
import { NAVIGATION_SCREEN } from '../../utils/constant'
import { scale } from '../../utils/scaling'
import useStyle from './styles'

const CREATE_ADDRESS = gql`
  ${createAddress}
`

const labelValues = [
  {
    title: 'Home',
    value: 'Home'
  },
  {
    title: 'Work',
    value: 'Work'
  },
  {
    title: 'Other',
    value: 'Other'
  }
]

const LATITUDE = 33.7001019
const LONGITUDE = 72.9735978
const LATITUDE_DELTA = 0.0022
const LONGITUDE_DELTA = 0.0021

function NewAddress() {
  const route = useRoute()
  const styles = useStyle()
  const addressRef = useRef()
  const { colors } = useTheme()
  const navigation = useNavigation()

  const [deliveryAddress, setDeliveryAddress] = useState('')
  const [deliveryDetails, setDeliveryDetails] = useState('')
  const [deliveryAddressError, setDeliveryAddressError] = useState('')
  const [deliveryDetailsError, setDeliveryDetailsError] = useState('')
  const [selectedLabel, setSelectedLabel] = useState(labelValues[0].value)
  const [region, setRegion] = useState({
    latitude: LATITUDE,
    latitudeDelta: LATITUDE_DELTA,
    longitude: LONGITUDE,
    longitudeDelta: LONGITUDE_DELTA
  })

  const regionObj = route.params ? route.params.regionChange : null

  useLayoutEffect(() => {
    navigation.setOptions({
      title: i18n.t('addAddress'),
      headerRight: null
    })
  }, [navigation])

  useEffect(() => {
    _getLocationAsync()
  }, [])

  useEffect(() => {
    if (regionObj !== null) regionChange(regionObj)
  }, [regionObj])

  const [mutate, { loading }] = useMutation(CREATE_ADDRESS, {
    onCompleted,
    onError
  })

  async function _getLocationAsync() {
    const { status } = await Location.requestForegroundPermissionsAsync()
    if (status === 'granted') {
      const location = await Location.getCurrentPositionAsync({
        enableHighAccuracy: true
      })
      const loc = {
        latitude: parseFloat(location.coords.latitude),
        latitudeDelta: LATITUDE_DELTA,
        longitude: parseFloat(location.coords.longitude),
        longitudeDelta: LONGITUDE_DELTA
      }
      setRegion(loc)
      regionChange(loc)
    } else {
      FlashMessage({
        message: 'Location permission not granted'
      })
    }
  }

  function regionChange(region) {
    Location.reverseGeocodeAsync({ ...region })
      .then(data => {
        if (data.length && addressRef.current !== null) {
          const location = data[0]
          const deliveryAddress = keys(location)
            .map(key => location[key])
            .join(' ')
          setDeliveryAddress(deliveryAddress)
          setRegion(region)

          addressRef.current.setValue(deliveryAddress)
        }
      })
      .catch(error => {
        console.log('Error : ', error)
      })
  }

  function onCompleted(data) {
    FlashMessage({
      message: 'Address added'
    })
    const cartAddress = route.params ? route.params.backScreen : null
    if (cartAddress === NAVIGATION_SCREEN.Cart) {
      navigation.navigate(NAVIGATION_SCREEN.Cart, {
        AddressObject: data.createAddress.addresses[0]
      })
    } else navigation.goBack()
  }

  function onError(error) {
    FlashMessage({
      message: `An error occured. Please try again. ${error}`
    })
  }

  return (
    <WrapperView>
      <KeyboardAvoidingView
        behavior={Platform.OS === 'ios' ? 'padding' : undefined}
        keyboardVerticalOffset={Platform.OS === 'android' ? 20 : 0}
        style={styles.flex}
        enabled>
        <View style={styles.flex}>
          <View style={styles.mapContainer}>
            <MapView
              style={styles.flex}
              scrollEnabled={false}
              zoomEnabled={false}
              zoomControlEnabled={false}
              rotateEnabled={false}
              cacheEnabled={true}
              showsUserLocation={false}
              initialRegion={{
                latitude: LATITUDE,
                latitudeDelta: LATITUDE_DELTA,
                longitude: LONGITUDE,
                longitudeDelta: LONGITUDE_DELTA
              }}
              region={region}
              provider={
                Platform.OS === 'android' ? PROVIDER_GOOGLE : PROVIDER_DEFAULT
              }
              onTouchMove={() => {
                navigation.navigate(NAVIGATION_SCREEN.FullMap, {
                  latitude: region.latitude,
                  longitude: region.longitude,
                  currentScreen: 'NewAddress'
                })
              }}>
              <Marker
                coordinate={{
                  latitude: region.latitude,
                  longitude: region.longitude
                }}>
                <Image
                  source={require('../../assets/images/markerEnatega.png')}
                  style={{ width: scale(43), height: scale(43) }}
                />
              </Marker>
            </MapView>
          </View>

          <ScrollView
            style={styles.flex}
            contentContainerStyle={{ flexGrow: 1 }}
            showsVerticalScrollIndicator={false}>
            <View style={styles.subContainer}>
              <View style={styles.upperContainer}>
                <View style={styles.labelButtonContainer}>
                  <View style={styles.labelTitleContainer}>
                    <TextDefault H5 bold>
                      Label As:
                    </TextDefault>
                  </View>
                  <View style={styles.buttonInline}>
                    {labelValues.map((label, index) => {
                      const isSelected = selectedLabel === label.value
                      return (
                        <TouchableOpacity
                          activeOpacity={0.5}
                          key={index}
                          style={
                            isSelected ? styles.activeLabel : styles.labelButton
                          }
                          onPress={() => {
                            setSelectedLabel(label.value)
                          }}>
                          {isSelected && (
                            <Ionicons
                              name="checkmark-circle"
                              size={20}
                              color={colors.lightBackground}
                            />
                          )}
                          <TextDefault
                            textColor={
                              isSelected
                                ? colors.lightBackground
                                : colors.placeHolderColor
                            }
                            bold
                            center>
                            {label.title}
                          </TextDefault>
                        </TouchableOpacity>
                      )
                    })}
                  </View>
                </View>
                <View style={styles.addressContainer}>
                  <FilledTextField
                    error={deliveryAddressError}
                    ref={addressRef}
                    value={deliveryAddress}
                    label={i18n.t('fullDeliveryAddress')}
                    labelFontSize={scale(12)}
                    fontSize={scale(12)}
                    activeLineWidth={0}
                    lineWidth={0}
                    labelHeight={20}
                    maxLength={100}
                    textColor={colors.fontMainColor}
                    baseColor={colors.fontMainColor}
                    errorColor={colors.errorColor}
                    tintColor={
                      !deliveryAddressError
                        ? colors.selected
                        : colors.errorColor
                    }
                    labelTextStyle={styles.labelStyle}
                    inputContainerStyle={styles.textContainer}
                    onChangeText={text => {
                      setDeliveryAddress(text)
                    }}
                    onBlur={() => {
                      setDeliveryAddressError(
                        !deliveryAddress.trim().length
                          ? 'Delivery address is required'
                          : null
                      )
                    }}
                  />
                  <View style={alignment.MTxSmall} />
                  <FilledTextField
                    error={deliveryDetailsError}
                    value={deliveryDetails}
                    label={i18n.t('deliveryDetails')}
                    labelFontSize={scale(12)}
                    fontSize={scale(12)}
                    textAlignVertical="top"
                    multiline={false}
                    maxLength={30}
                    activeLineWidth={0}
                    lineWidth={0}
                    labelHeight={20}
                    textColor={colors.fontMainColor}
                    baseColor={colors.fontMainColor}
                    errorColor={colors.errorColor}
                    tintColor={
                      !deliveryAddressError
                        ? colors.selected
                        : colors.errorColor
                    }
                    labelTextStyle={styles.labelStyle}
                    inputContainerStyle={styles.textContainer}
                    onChangeText={text => {
                      setDeliveryDetails(text)
                    }}
                    onBlur={() => {
                      setDeliveryDetailsError(
                        !deliveryDetails.trim().length
                          ? 'Delivery details is required'
                          : null
                      )
                    }}
                  />
                </View>
              </View>
              <TouchableOpacity
                disabled={loading}
                onPress={() => {
                  const deliveryAddressError = !deliveryAddress.trim().length
                    ? 'Delivery address is required'
                    : null
                  const deliveryDetailsError = !deliveryDetails.trim().length
                    ? 'Delivery details is required'
                    : null

                  setDeliveryAddressError(deliveryAddressError)
                  setDeliveryDetailsError(deliveryDetailsError)

                  if (
                    deliveryAddressError === null &&
                    deliveryDetailsError === null
                  ) {
                    mutate({
                      variables: {
                        addressInput: {
                          latitude: `${region.latitude}`,
                          longitude: `${region.longitude}`,
                          delivery_address: deliveryAddress.trim(),
                          details: deliveryDetails.trim(),
                          label: selectedLabel
                        }
                      }
                    })
                  }
                }}
                activeOpacity={0.5}
                style={styles.saveBtnContainer}>
                {loading ? (
                  <View style={styles.spinnerView}>
                    <Spinner
                      backColor="transparent"
                      spinnerColor={colors.buttonText}
                    />
                  </View>
                ) : (
                  <TextDefault textColor={colors.buttonText} H5 bold>
                    {i18n.t('saveContBtn')}
                  </TextDefault>
                )}
              </TouchableOpacity>
              <TouchableOpacity
                style={[alignment.PBsmall, alignment.PTsmall]}
                activeOpacity={0.7}
                onPress={() => navigation.goBack()}>
                <TextDefault H5 bold>
                  {'Cancel'}
                </TextDefault>
              </TouchableOpacity>
            </View>
          </ScrollView>
        </View>
      </KeyboardAvoidingView>
    </WrapperView>
  )
}

export default NewAddress
