/**
 * React Native Full App (https://store.enappd.com/product/react-native-full-app)
 *
 * Copyright © 2019-present Enappd. All rights reserved.
 *
 * This source code is licensed as per the terms found in the
 * LICENSE.md file in the root directory of this source tree.
 */

import React from 'react';
import {
  ActivityIndicator,
  Text,
  Platform,
  StyleSheet,
  View,
} from 'react-native';
import { NavigationDrawerScreenProps } from 'react-navigation-drawer';
import { Container, Button, Content } from 'native-base';
import HeaderCommon from '../../components/common/header';
import * as Location from 'expo-location';
import * as Permissions from 'expo-permissions';
import * as Font from 'expo-font';
interface Iprops extends NavigationDrawerScreenProps { }
const EXAMPLES = [
  '1 Hacker Way',
  { latitude: 49.28, longitude: -123.12 },
  'Palo Alto Caltrain Station (this one will error)',
  'Rogers Arena, Vancouver',
  { latitude: 0, longitude: 0 },
];

export default class GeocodingExample extends React.Component<Iprops> {
  static navigationOptions = {
    title: 'Geocoding',
  };

  toggleMenu = () => this.props.navigation.toggleDrawer();

  state = {
    selectedExample: EXAMPLES[0],
    result: '',
    inProgress: false,
    fontLoaded: false,
    error: false,
  };

  async componentDidMount() {
    Permissions.askAsync(Permissions.LOCATION);
    await Font.loadAsync({
      montserrat: require('../../assets/Fonts/Montserrat.ttf'),
    });
    this.setState({ fontLoaded: true });
  }

  render() {
    let { selectedExample, fontLoaded } = this.state;

    return (
      <Container>
        <HeaderCommon title="Geocode" toggleMenu={this.toggleMenu} />
        {fontLoaded ? (
          <Content scrollEnabled={true}>
            <View style={styles.container}>
              <View style={styles.headerContainer}>
                <Text style={styles.headerText}>
                  Geocoding is provide geographical coordinates corresponding to
                  a location.
                </Text>
                <Text style={styles.headerText}>
                  Reverse geocoding is the process of back (reverse) coding of a
                  point location (latitude, longitude) to a readable address or
                  place name
                </Text>
                <Text style={styles.headerText}>
                  For Geolocation - Select location from 'Location String' and Tap
                  "GeoCode"
                </Text>
                <Text style={styles.headerText}>
                  For Reverse Geolocation - Select Coordinates from 'Latitude and Longitude' section and Tap
                  "Reverse GeoCode"
                </Text>
              </View>

              <View style={styles.examplesContainer}>
                <Text style={styles.headerText}>Location String</Text>
                {EXAMPLES.map(this._renderExample)}
              </View>

              <View style={styles.examplesContainer}>
                <Text style={styles.headerText}>Latitude and Longitude</Text>
                {EXAMPLES.map(this._renderExampleLatLng)}
              </View>

              <View style={styles.separator} />

              <View style={styles.actionContainer}>
                <Button
                  style={styles.optionButton}
                  onPress={this._attemptGeocodeAsync}
                  disabled={typeof selectedExample !== 'string'}
                >
                  <Text style={styles.white}>Geocode</Text>
                </Button>
                <Button
                  style={styles.optionButton}
                  onPress={this._attemptReverseGeocodeAsync}
                  disabled={typeof selectedExample !== 'object'}
                >
                  <Text style={styles.white}>Reverse Geocode</Text>
                </Button>
              </View>

              <View style={styles.separator} />

              {this._maybeRenderResult()}
            </View>
          </Content>
        ) : null}
      </Container>
    );
  }

  _attemptReverseGeocodeAsync = async () => {
    this.setState({ inProgress: true });
    try {
      const selectedValue: any = this.state.selectedExample;
      let result = await Location.reverseGeocodeAsync(selectedValue);
      this.setState({ result });
    } catch (e) {
      this.setState({ error: e });
    } finally {
      this.setState({ inProgress: false });
    }
  };

  _attemptGeocodeAsync = async () => {
    this.setState({ inProgress: true, error: null });
    try {
      const selectedValue: any = this.state.selectedExample;
      let result = await Location.geocodeAsync(selectedValue);
      this.setState({ result });
    } catch (e) {
      this.setState({ error: e.message });
    } finally {
      this.setState({ inProgress: false });
    }
  };

  _maybeRenderResult = () => {
    let { selectedExample } = this.state;
    let text =
      typeof selectedExample === 'string'
        ? selectedExample
        : JSON.stringify(selectedExample);

    if (this.state.inProgress) {
      return <ActivityIndicator style={{ marginTop: 10 }} />;
    }
    if (this.state.result) {
      return (
        <Text style={styles.resultText}>
          {text} resolves to {JSON.stringify(this.state.result)}
        </Text>
      );
    } else if (this.state.error) {
      return (
        <Text style={styles.errorResultText}>
          {text} cannot resolve: {JSON.stringify(this.state.error)}
        </Text>
      );
    }
  };

  _renderExample = (example: any, i: any) => {
    let { selectedExample } = this.state;
    let isSelected = selectedExample === example;
    if (typeof example === 'string') {
      let text = JSON.stringify(example);

      return (
        <Button
          style={styles.optionButton}
          onPress={() => this._selectExample(example)}
        >
          <Text style={styles.white}>{text}</Text>
        </Button>
      );
    }
    return <></>;
  };

  _renderExampleLatLng = (example: any, i: any) => {
    let { selectedExample } = this.state;
    let isSelected = selectedExample === example;
    if (typeof example === 'string') {
      return <></>;
    }
    let text = JSON.stringify(example);

    return (
      <Button
        style={styles.optionButton}
        onPress={() => this._selectExample(example)}
      >
        <Text style={styles.white}>{text}</Text>
      </Button>
    );
  };

  _selectExample = (example: any) => {
    if (this.state.inProgress) {
      return;
    }

    this.setState({ selectedExample: example, result: '', error: '' });
  };
}

const styles = StyleSheet.create({
  container: {
    // flex: 1,
  },
  separator: {
    height: 1,
    backgroundColor: '#eee',
    marginTop: 10,
    marginBottom: 5,
  },
  headerText: {
    fontSize: 18,
    fontWeight: 'normal',
    marginBottom: 5,
    fontFamily: 'montserrat',
  },
  headerContainer: {
    borderBottomWidth: 1,
    borderBottomColor: '#eee',
    marginHorizontal: 20,
    marginBottom: 0,
    marginTop: 20,
  },
  exampleText: {
    fontSize: 15,
    color: '#ccc',
    marginVertical: 10,
    fontFamily: 'montserrat',
  },
  examplesContainer: {
    paddingTop: 15,
    paddingBottom: 5,
    paddingHorizontal: 20,
  },
  selectedExampleText: {
    color: 'black',
    fontFamily: 'montserrat',
  },
  resultText: {
    padding: 20,
    fontFamily: 'montserrat',
  },
  actionContainer: {
    marginVertical: 10,
  },
  errorResultText: {
    padding: 20,
    color: 'red',
  },
  optionButton: {
    marginBottom: 20,
    justifyContent: 'center',
    width: '100%',
  },
  white: {
    color: 'white',
    fontFamily: 'montserrat',
  },
  button: {
    ...Platform.select({
      android: {
        marginBottom: 10,
      },
    }),
  },
});
