/** Screen for listing notifications **/
import _ from 'lodash';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Dimensions, Image, SectionList, Text, View } from 'react-native';
import NotificationItem from '../../components/lists/NotificationItem';
import { Spacer, Spinner } from '../../components/common';
import {
  fetchProfileInfoByProfileId,
  profileListReset,
  notificationsFetch
} from '../../actions';
import {
  REFERRAL_RECEIVED,
  REQUEST_ACCEPTED,
  REQUEST_SENT,
  REQUEST_RECEIVED
} from '../NotificationListTypes';
import colors from '../../config/colors.json';
import { strings } from '../../locales/i18n';

const LOGO = require('../../../assets/tagfer_brand_and_logo_512.png');

const SCREEN_HEIGHT = Dimensions.get('window').height;

let sections = [];

class NotificationList extends Component {
  state = { loading: true, noItems: false };

  /**
  * Component Did Mount
  **/
  componentWillMount() {
    this.props.profileListReset();
    this.props.notificationsFetch();
  }

  /**
  * Component Will Receive Props
  **/
  componentWillReceiveProps(nextProps) {
    if (nextProps.notifications && nextProps.notifications.length > 0 && nextProps.profiles.length === 0) {
      const userIds = [];
      const profileIds = [];
      for (let i = 0; i < nextProps.notifications.length; i++) {
        userIds.push(nextProps.notifications[i].otherUserId);
        profileIds.push(nextProps.notifications[i].otherProfileId);
      }

      if (userIds.length > 0) {
        this.props.fetchProfileInfoByProfileId(userIds, profileIds);
      }
    }
    if (nextProps.profiles) {
      this.createNotificationSections(nextProps.notifications, nextProps.profiles);
    }
    if (!_.isEqual(this.props.notifications, nextProps.notifications) || this.props.success) {
      this.setState({ loading: false });
      if (nextProps.notifications.length === 0) {
        this.setState({ noItems: true });
      }
    }
  }

  /**
  * Formats all notifications into groups and creates headers for the SectionList
  **/
  createNotificationSections(notifications, profiles) {
    for (let i = 0; i < notifications.length; i++) {
      for (let j = 0; j < profiles.length; j++) {
        if (notifications[i].otherProfileId === profiles[j].uid) {
          // combines the notification and profile data via profileId matching
          sections.push({
            title: notifications[i].notificationType,
            data: Object.assign(notifications[i], profiles[j])
          });
          break;
        }
      }
    }

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

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

  /**
  * Creates the Section Headers that divide notification groups
  **/
  renderSectionHeader = ({ section }) => {
    switch (section.title) {
      case REFERRAL_RECEIVED:
        return (
          <View style={styles.sectionContainer}>
            <Text style={styles.sectionTitle}>{strings('notification.listHeader_referrals')}</Text>
          </View>
        );

      case REQUEST_ACCEPTED:
        return (
          <View style={styles.sectionContainer}>
            <Text style={styles.sectionTitle}>{strings('notification.listHeader_acceptedRequests')}</Text>
          </View>
        );

      case REQUEST_RECEIVED:
        return (
          <View style={styles.sectionContainer}>
            <Text style={styles.sectionTitle}>{strings('notification.listHeader_receivedRequests')}</Text>
          </View>
        );

      case REQUEST_SENT:
        return (
          <View style={styles.sectionContainer}>
            <Text style={styles.sectionTitle}>{strings('notification.listHeader_sentRequests')}</Text>
          </View>
        );

      default:
        return (
          <View style={styles.sectionContainer}>
            <Text style={styles.sectionTitle}>{section.title}</Text>
          </View>
        );
    }
  }

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

  /**
  * Render method
  **/
  render() {
    if (this.state.loading) {
      return (
        <View style={{ flex: 1, backgroundColor: colors.white }}>
          <Spinner size="large" />;
        </View>
      );
    }

    if (this.state.noItems) {
      return (
        <View style={styles.noItemsViewStyle}>
          <Spacer />
          <Image
            source={LOGO}
            style={styles.logoStyle}
          />
          <Spacer space={45} />

          <View>
          <Text style={styles.noItemsTextStyle}>
            {strings('notification.noItems')}
          </Text>
          </View>
        </View>
      );
    }

    return (
      <View style={{ flex: 1, backgroundColor: colors.white, minHeight: SCREEN_HEIGHT }}>
        <SectionList
          keyExtractor={this.keyExtractor}
          renderSectionHeader={this.renderSectionHeader}
          renderItem={this.renderItem}
          sections={sections}
        />
      </View>
    );
  }
}

const styles = {
  sectionContainer: {
    borderBottomWidth: 1,
    borderBottomColor: colors.transparent,
    backgroundColor: colors.offWhite
  },
  sectionTitle: {
    color: colors.black,
    fontSize: 14,
    marginBottom: 8,
    marginLeft: 16,
    marginRight: 16,
    marginTop: 24,
    opacity: 0.8
  },
  noItemsViewStyle: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'flex-start',
    alignItems: 'center',
    backgroundColor: colors.white,
    height: SCREEN_HEIGHT
  },
  logoStyle: {
    height: 200,
    width: 200,
    marginTop: 15,
    marginBottom: 15
  },
  noItemsTextStyle: {
    fontSize: 18,
    marginHorizontal: 15
  }
};

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

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

  const { success } = state.notificationStatus;

  return { profiles, notifications, success };
};

export default connect(mapStateToProps, {
  fetchProfileInfoByProfileId, profileListReset, notificationsFetch,
})(NotificationList);
