/** Screen for listing contacts **/
import _ from 'lodash';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { SectionList, Text, View } from 'react-native';
import { SearchBar } from 'react-native-elements';
import { contactsFetch, friendsFetch } from '../../actions';
import ContactItem from './ContactItem';
import { Spacer, Spinner } from '../../components/common';
import colors from '../../config/colors.json';
import { strings } from '../../locales/i18n';

let sections = [];
let contactsAndFriends = [];

class ContactList extends Component {

  state = { searchTerm: '', loading: true };

  /**
  * Component Did Mount
  **/
  componentDidMount() {
    this.props.friendsFetch();
    this.props.contactsFetch();
    this.mergeFriendsAndContacts(this.props.contacts, this.props.friends);

    this.createContactSections(contactsAndFriends);
    this.setState({ loading: false });
  }

  /**
  * Component Will Receive Props
  * Merge contacts and friends if both exist, otherwise use
  * the one that exists
  **/
  componentWillReceiveProps(nextProps) {
    if (nextProps.contacts && nextProps.friends) {
      this.mergeFriendsAndContacts(nextProps.contacts, nextProps.friends);
      this.createContactSections(contactsAndFriends);
    } else if (nextProps.contacts) {
      nextProps.contacts.sort((a, b) => this.compare(a, b));
      contactsAndFriends = nextProps.contacts;
      this.createContactSections(nextProps.contacts);
    } else if (nextProps.friends) {
      nextProps.friends.sort((a, b) => this.compare(a, b));
      contactsAndFriends = nextProps.friends;
      this.createContactSections(nextProps.friends);
    }
  }

  /**
  * Merges the friends and contacts for all of the tabs
  **/
  mergeFriendsAndContacts(currentContacts, currentFriends) {
    contactsAndFriends = currentContacts.concat(currentFriends);
    contactsAndFriends.sort((a, b) => this.compare(a, b));
  }

  /**
  * Formats all contacts into groups and creates headers for the SectionList
  **/
  createContactSections(contacts) {
    for (let i = 0; i < contacts.length; i++) {
      sections.push({ title: contacts[i].fullName[0], data: contacts[i] });
    }
    sections = _.groupBy(contacts, d => d.fullName[0].toUpperCase());

    sections = _.reduce(sections, (acc, next, index) => {
      acc.push({
        title: index,
        data: next
      });
      return acc;
    }, []);
  }

  /**
  * Used for sorting contacts based on name property
  **/
  compare(a, b) {
    if (a.fullName.toLowerCase() < b.fullName.toLowerCase()) {
      return -1;
    }
    if (a.fullName.toLowerCase() > b.fullName.toLowerCase()) {
      return 1;
    }
    return 0;
  }

  /**
  * Filters search results based on searchBar input
  * Checks if the term is found in either name field, titleAndCompany, or tagferId
  * Then creates headers based on found contacts
  **/
  searchUpdated(term) {
    contactsAndFriends.sort((a, b) => this.compare(a, b));
    let filteredProps = contactsAndFriends;

    filteredProps = filteredProps.filter(
      (contactContainer) => {
        if (contactContainer.fullName.toLowerCase().indexOf(term) !== -1) {
          return true;
        }
        if (contactContainer.tagferId) {
          if (contactContainer.tagferId.toLowerCase().indexOf(term) !== -1) {
            return true;
          }
        }
        if (contactContainer.titleAndCompany) {
          if (contactContainer.titleAndCompany.toLowerCase().indexOf(term) !== -1) {
            return true;
          }
        }
        return false;
      }
    );

    this.createContactSections(filteredProps);
    this.setState({ searchTerm: term });
  }

  /**
  * Creates a unique key for each contact
  **/
  keyExtractor = (item) => {
    return `${item.uid}`;
  }

  /**
  * Creates the Section Headers that divide contact groups
  **/
  renderSectionHeader = ({ section }) => {
    return (
      <View style={styles.sectionContainer}>
        <Text style={styles.sectionTitle}>{section.title}</Text>
      </View>
    );
  }

  /**
  * Renders each row of the list
  **/
  renderItem = ({ item }) => {
    return <ContactItem {...this.props} item={item} />;
  }

  /**
  * Render method
  **/
  render() {
    if (this.state.loading) {
      return (
        <Spinner size="large" />
      );
    }
    return (
      <View style={{ flex: 1 }}>
        <SearchBar
          onChangeText={(term) => this.searchUpdated(term.toLowerCase())}
          containerStyle={{ backgroundColor: colors.white }}
          inputStyle={{ backgroundColor: colors.white }}
          placeholder={strings('common.search.searchPlaceholder_contacts')}
          autoCorrect={false}
          autoCapitalize='none'
        />
        <SectionList
          keyExtractor={this.keyExtractor}
          renderSectionHeader={this.renderSectionHeader}
          renderItem={this.renderItem}
          sections={sections}
        />
        <Spacer space={45} />
      </View>
    );
  }
}

const styles = {
  sectionContainer: {
    borderBottomWidth: 1,
    borderBottomColor: colors.lightGrey,
    backgroundColor: colors.white
  },
  sectionTitle: {
    color: colors.black,
    fontSize: 14,
    marginBottom: 8,
    marginLeft: 16,
    marginRight: 16,
    marginTop: 24,
    opacity: 0.8
  }
};

const mapStateToProps = state => {
  // converts contact object of objects into contact array of objects
  const contacts = _.map(state.contacts, (val, uid) => {
    return { ...val, uid };
  });

  //converts friend object of objects into friend array of objects
  const friends = _.map(state.friends, (val, uid) => {
    return { ...val, uid };
  });

  return { contacts, friends };
};

export default connect(mapStateToProps, {
  contactsFetch, friendsFetch
})(ContactList);
