import React from 'react';
import { Alert, Dimensions, Text, View, FlatList, TouchableOpacity, Platform, ActivityIndicator } from 'react-native';
import { Button, CheckBox } from 'react-native-elements';
import OpenAppSettings from 'react-native-app-settings';
import Permissions from 'react-native-permissions';
import Contacts from 'react-native-contacts';

import { strings } from '../../locales/i18n';
import { fetchAuth } from '../../utils/fetch';
import { showFlashErrorMessage } from '../../utils/errorHandler';
import { loadSignupState, saveSignupState, isContactSelected } from '../../realm/actions/AuthActions';

import colors from '../../config/colors.json';
import endpoints from '../../config/apiEndpoints';
import ContactListItem from '../../components/new/ContactListItem';

export default class SignupScreenFive extends React.Component {
  static navigationOptions = {
    title: strings('contact.importScreen_title'),
    headerStyle: { borderBottomWidth: 0, backgroundColor: colors.offWhite },
    headerTintColor: '#0D497E',
    headerRight: <Text style={{ color: colors.middleGrey, marginRight: 5 }}>5/6</Text>
  };

  constructor(props) {
    super(props);
    this.state = {
      allContacts: [],
      selectedContacts: new Map(),
      isUpdate: false,
      loading: true
    };

    loadSignupState(5).then(result => {
      this.isUpdate = result.isUpdate;
      this.setState({ ...result.prevState }, () => this.fetchContacts());
    });

    this.onSelectAll = this.onSelectAll.bind(this);
    this.onSaveButtonPress = this.onSaveButtonPress.bind(this);
  }

  // Handles when the user presses on the select all button
  onSelectAll() {
    const { allContacts, selectedContacts } = this.state;
    if (allContacts.length === selectedContacts.size) {
      this.setState({ selectedContacts: new Map() });
    } else {
      this.setState({ selectedContacts: this.selectAllContacts(allContacts) });
    }
  }

  // When a user clicks on a single contact
  onSelectContact(recordID, index) {
    this.setState((state) => {
      const selectedContacts = new Map(state.selectedContacts);
      
      if (selectedContacts.has(recordID)) {
        selectedContacts.delete(recordID);
      } else {
        const phoneNumbers = this.state.allContacts[index].phoneNumbers;
        selectedContacts.set(recordID, phoneNumbers);
      }

      return { selectedContacts };
    });
  }

  // Sends the request and navigates the user to next page.
  // Saves the users selected contacts and saves the request result in realm to be processed later. 
  async onSaveButtonPress() {
    const { selectedContacts } = this.state;
    saveSignupState(-5, selectedContacts.keys());
    if (selectedContacts.size === 0) {
      this.props.navigation.navigate('signup6');
      return saveSignupState(5, { tagferIds: [], phoneNumbers: [] }, this.isUpdate);
    }

    this.setState({ loading: true });
    const phoneNumbers = [];
    for (const record of selectedContacts.values()) {
      phoneNumbers.push(...record.map(entry => entry.number));
    }

    const resp = await fetchAuth(endpoints.findUsersByPhone, { phoneNumbers });
    this.setState({ loading: false });

    if (resp.error) {
      return showFlashErrorMessage(resp.error);
    }
    
    this.props.navigation.navigate('signup6');
    saveSignupState(5, { tagferIds: resp.inNetwork, phoneNumbers: resp.outNetwork }, this.isUpdate);
  }

  // BEGIN: Fetch contacts
  getContacts() {
    Contacts.getAllWithoutPhotos((error, contacts) => {
      if (error) { 
        this.props.navigation.navigate('signup6');
      } else {
        const selectedContacts = this.isUpdate ? this.restoreSelectedContacts(contacts) : this.selectAllContacts(contacts);
        this.setState({ allContacts: contacts, selectedContacts, loading: false });
      }
    });
  }

  requestPermissions() {
    Permissions.request('contacts').then(permission => {
      if (permission === 'authorized') return this.getContacts();
      this.props.navigation.navigate('signup6');
    });
  }

  selectAllContacts(contacts) {
    const selectedContacts = new Map();
    for (let i = 0; i < contacts.length; i++) {
      selectedContacts.set(contacts[i].recordID, contacts[i].phoneNumbers);
    }

    return selectedContacts;
  }

  restoreSelectedContacts(contacts) {
    const selectedContacts = new Map();
    for (let i = 0; i < contacts.length; i++) {
      if (isContactSelected(contacts[i].recordID)) {
        selectedContacts.set(contacts[i].recordID, contacts[i].phoneNumbers);
      }
    }

    return selectedContacts;
  }

  createSettingsAlert() {
    Alert.alert(
      'Contacts Access Denied', 
      'To enable access, tap Settings and turn on Contacts', 
      [
        { text: 'Cancel', onPress: () => this.props.navigation.navigate('signup6') },
        { text: 'Settings', onPress: () => OpenAppSettings.open() }
      ],
      { cancelable: false }
    );
  }

  fetchContacts() {
    Permissions.check('contacts').then(permission => {      
      if (Platform.OS === 'ios') {
        if (permission === 'restricted') return this.props.navigation.navigate('signup6');
        if (permission === 'denied') return this.createSettingsAlert();
        
        return this.getContacts();
      }

      if (Platform.OS === 'android') {
        return permission === 'restricted' ? this.createSettingsAlert() : this.requestPermissions();
      }
    });
  }
  // END: Fetch Contacts

  renderItem(contact, index) {
    const selected = this.state.selectedContacts.has(contact.recordID);
    return <ContactListItem contact={contact} selected={selected} onPress={() => this.onSelectContact(contact.recordID, index)} />;
  }

  renderActivityIndicator() {
    return (
    <View style={{ flexDirection: 'row', justifyContent: 'center', marginTop: 20 }}>
      <ActivityIndicator size='large' color={colors.labelBlue} />
    </View>
    );
  }

  render() {
    return (
      <View style={styles.container}>
        {/* INSTRUCTIONS */}
        <Text style={styles.instructions}>{strings('contact.importScreen_description')}</Text>
        
        {/* FLAT LIST OF CONTACTS */}
        <FlatList 
          ListHeaderComponent={<ListHeader isChecked={this.state.selectedContacts.size === this.state.allContacts.length} onPress={this.onSelectAll} onSkip={() => this.props.navigation.navigate('signup6')} />}
          data={this.state.allContacts}
          extraData={this.state}
          renderItem={({ item, index }) => this.renderItem(item, index)}
          keyExtractor={(item) => item.recordID}
          style={{ flex: 1, marginHorizontal: 10 }}
          ListEmptyComponent={this.renderActivityIndicator()}
        />

        {/* SAVE AND CONTINUE BUTTON */}
        <Button
          onPress={this.onSaveButtonPress}
          title={strings('common.buttons.saveAndContinue')}
          loading={this.state.loading}
          disabled={this.state.loading}
          buttonStyle={styles.buttonStyle}
          fontSize={20}
          iconRight={styles.chevronIconStyle}
        />
      </View>
    );
  }
}

const ListHeader = ({ isChecked, onPress, onSkip }) => (
  <View style={styles.headerContainer}>
    {/* CHECKBOX */}
    <CheckBox
      iconType='material'
      checkedIcon='check-box'
      uncheckedIcon='check-box-outline-blank'
      uncheckedColor={colors.darkGrey}
      checkedColor={colors.labelBlue}
      onPress={onPress}
      onIconPress={onPress}
      containerStyle={styles.checkBoxContainer}
      size={28}
      title={isChecked ? 'Deselect All' : 'Select All'}
      textStyle={styles.checkBoxTextStyle}
      checked={isChecked}
    />

    {/* SKIP BUTTON */}
    <TouchableOpacity style={{ marginRight: 15 }} onPress={onSkip}>
      <Text style={styles.skipButton}>SKIP</Text>
    </TouchableOpacity>
  </View>
);

const SCREEN_WIDTH = Dimensions.get('window').width;
const styles = {
  container: {
    flex: 1,
    backgroundColor: colors.offWhite
  },
  headerContainer: {
    flex: 1,
    justifyContent: 'space-between',
    alignItems: 'center',
    backgroundColor: colors.white,
    flexDirection: 'row',
    borderBottomColor: '#E0E3EF',
    borderBottomWidth: 2
  },
  checkBoxContainer: {
    backgroundColor: colors.white,
    borderWidth: 0
  },
  checkBoxTextStyle: {
    fontSize: 16,
    fontWeight: 'normal',
    color: colors.darkGrey
  },
  instructions: {
    left: 20,
    width: '90%',
    marginTop: 20,
    marginBottom: 30,
    fontSize: 16,
    color: colors.grey,
    textAlign: 'justify'
  },
  skipButton: {
    fontSize: 12,
    color: colors.darkGrey 
  },
  buttonStyle: {
    width: SCREEN_WIDTH * 0.9,
    marginTop: 15,
    marginBottom: 30,
    borderRadius: 5,
    backgroundColor: colors.buttonBlue
  },
  chevronIconStyle: {
    name: 'chevron-right', 
    color: colors.white,
    size: 30,
    style: { marginLeft: 0 }
  }
};
