/** Screen for listing socialContacts **/
import _ from 'lodash';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { FlatList, View } from 'react-native';
import { SearchBar } from 'react-native-elements';
import {
  profileFetch,
  friendsFetch,
  notificationsFetch,
  socialListReset,
  socialSearch
} from '../../actions';
import NetworkSearchItem from '../../components/lists/NetworkSearchItem';
import { Spinner } from '../../components/common';
import colors from '../../config/colors.json';
import { strings } from '../../locales/i18n';

let searchResults = [];

class SocialList extends Component {
  constructor() {
    super();
    this.onChangeTextDelayed = _.debounce(this.searchUpdated, 250);
    this.state = { searchTerm: '', loading: true };
  }

  /**
  * Component Did Mount
  **/
  componentDidMount() {
    this.props.profileFetch();
    this.props.friendsFetch();
    this.props.notificationsFetch();
    this.props.socialListReset();
    this.setState({ loading: false });
  }

  /**
  * Component Will Receive Props
  **/
  componentWillReceiveProps(nextProps) {
    if (nextProps.socialContacts) {
      this.populateSearchResults(nextProps);
    }
  }

  /**
  * Formats searchResults for the FlatList
  **/
  populateSearchResults(nextProps) {
    if (nextProps) {
      nextProps.socialContacts.sort((a, b) => this.compare(a, b));
      searchResults = this.removeMyProfilesFromSearchResults(nextProps.socialContacts);
      searchResults = this.removeMyFriendsFromSearchResults(nextProps.socialContacts);
      searchResults = this.removeMyNotificationsFromSearchResults(nextProps.socialContacts);
    } else {
      this.props.socialContacts.sort((a, b) => this.compare(a, b));
      searchResults = this.removeMyProfilesFromSearchResults(this.props.socialContacts);
      searchResults = this.removeMyFriendsFromSearchResults(this.props.socialContacts);
      searchResults = this.removeMyNotificationsFromSearchResults(this.props.socialContacts);
    }
  }

  /**
  * Removes any of the user's profiles from displaying as options for them to add
  **/
  removeMyProfilesFromSearchResults(searchResultsContacts) {
    const profiles = this.props.profiles;
    const searchContacts = searchResultsContacts;

    for (let i = 0; i < searchContacts.length; i++) {
      for (let j = 0; j < profiles.length; j++) {
        if (searchContacts[i].uid === profiles[j].uid) {
          searchContacts.splice(i, 1);
          i--;
          break;
        }
      }
    }
    return searchContacts;
  }

  /**
  * Removes any of the user's current friends from displaying on search results
  **/
  removeMyFriendsFromSearchResults(searchResultsContacts) {
    const friends = this.props.friends;
    const searchContacts = searchResultsContacts;

    for (let i = 0; i < searchContacts.length; i++) {
      for (let j = 0; j < friends.length; j++) {
        if (searchContacts[i].uid === friends[j].uid) {
          searchContacts.splice(i, 1);
          i--;
          break;
        }
      }
    }
    return searchContacts;
  }

  /**
  * Removes any of the user's current notifications from displaying on search results
  **/
  removeMyNotificationsFromSearchResults(searchResultsContacts) {
    const notifications = this.props.notifications;
    const searchContacts = searchResultsContacts;

    for (let i = 0; i < searchContacts.length; i++) {
      for (let j = 0; j < notifications.length; j++) {
        if (searchContacts[i].profileId === notifications[j].otherProfileId) {
          searchContacts.splice(i, 1);
          i--;
          break;
        }
      }
    }
    return searchContacts;
  }

  /**
  * Used for sorting searchResults based on fullName 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
  **/
  searchUpdated = (term) => {
    const trimmedTerm = term.trim();
    if (trimmedTerm.length <= 2) {
      this.props.socialListReset();
    } else {
      this.props.socialSearch(trimmedTerm);
      this.populateSearchResults();

      this.setState({ searchTerm: trimmedTerm });
    }
  }

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

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

  /**
  * Render method
  **/
  render() {
    if (this.state.loading) {
      return (
        <Spinner size="large" />
      );
    }
    return (
      <View style={{ flex: 1 }}>
        <SearchBar
          onChangeText={this.onChangeTextDelayed}
          containerStyle={{ backgroundColor: colors.white }}
          inputStyle={{ backgroundColor: colors.white }}
          placeholder={strings('common.search.searchPlaceholder_network')}
          autoCorrect={false}
          autoCapitalize='none'
        />
        <FlatList
          keyExtractor={this.keyExtractor}
          renderItem={this.renderItem}
          data={searchResults}
        />
      </View>
    );
  }
}

const mapStateToProps = state => {
  // converts Profile objects into profile arrays
  const profiles = _.map(state.profiles, (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 };
  });

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

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

  return { profiles, friends, notifications, socialContacts };
};

export default connect(mapStateToProps, {
  profileFetch, friendsFetch, notificationsFetch, socialListReset, socialSearch
})(SocialList);
