import React, { Component } from 'react';
import {
  ActivityIndicator,
  Alert,
  FlatList,
  LayoutAnimation,
  StyleSheet,
  Text,
  TouchableNativeFeedback,
  View,
} from 'react-native';
import { Icon } from 'react-native-elements';
import { NavigationScreenProps } from 'react-navigation';
import { connect, Dispatch } from 'react-redux';
import { ChatActions, NavActions } from '../actions';
import { ChatInput, EmptyView, MessageItem } from '../components/common';
import { Colors, Header } from '../components/ui';
import { getOppositeRole } from '../utils/RoleManager';

import {
  BasicUserInfo,
  ChatRoom as ChatRoomData,
  Conversation,
  Message,
  RootState,
  User,
  UserRole,
} from '../models';

interface OwnProps extends NavigationScreenProps<{ conversationId: string }> { }

interface StateProps {
  loading: boolean;
  data: ChatRoomData;
  participant: BasicUserInfo;
  user: User;
  isMuted: boolean;
  conversation: Conversation;
}

interface DispatchProps {
  onToggleMute: (muted: boolean) => void;
  onSendMessageRequest: (recipientId: string, msg: string) => void;
  onEmployerProfileRequested: (employerId: string) => void;
  onEmployeeProfileRequested: (employeeId: string) => void;
}

interface State {
  inputText: string;
}

export class ChatRoomComponent extends Component<StateProps & DispatchProps, State> {

  state = {
    inputText: '',
  };

  toggleMute = () => {
    if (!this.props.isMuted) {
      Alert.alert(
        'Potwierdź',
        'Wyciszając konwersację nie będziesz otrzymywać żadnych powiadomień od tej osoby',
        [
          { text: 'Anuluj', onPress: null, style: 'cancel' },
          { text: 'OK', onPress: () => this.props.onToggleMute(true) },
        ],
        { cancelable: false },
      );
    } else {
      this.props.onToggleMute(false);
    }
  }

  onChangeText = (inputText: string) => {
    this.setState({ inputText });
  }

  onParticipantProfileRequest = () => {
    const { user, participant, onEmployeeProfileRequested, onEmployerProfileRequested } = this.props;
    if (user.role === UserRole.EMPLOYEE) {
      onEmployerProfileRequested(participant.id);
    } else {
      onEmployeeProfileRequested(participant.id);
    }
  }

  onSendRequest = () => {
    if (this.state.inputText.length > 0) {
      this.props.onSendMessageRequest(this.props.participant.id, this.state.inputText.trim());
      this.setState({ inputText: '' });
    }
  }

  getMsgKey = (msg: Message) => msg.id;

  renderItem = ({ item }: { item: Message & { hasTimestamp: boolean } }) => (
    <MessageItem
      foreignColor={
        this.props.user.role === UserRole.EMPLOYEE
          ? Colors.employee.primary
          : Colors.employer.primary
      }
      own={this.props.user.body.id === item.authorId}
      hasTimestamp={item.hasTimestamp}
      message={item}
    />
  )

  componentWillUpdate() {
    LayoutAnimation.easeInEaseOut();
  }

  renderMuteButton() {
    const name = this.props.isMuted
      ? 'notifications-off'
      : 'notifications';
    return (
      <TouchableNativeFeedback onPress={this.toggleMute}>
        <Icon
          name={name}
          color={'white'}
          containerStyle={{ marginRight: 8 }}
        />
      </TouchableNativeFeedback>
    );
  }

  renderEmpty() {
    return <EmptyView text={'Brak wiadomości'} />;
  }

  renderLoading() {
    return <ActivityIndicator />;
  }

  renderHeaderTitle(title: string) {
    return (
      <View style={styles.headerTitle}>
        <TouchableNativeFeedback onPress={this.onParticipantProfileRequest}>
          <View>
            <Text style={{ color: 'white', textAlign: 'center' }}>
              {title}
            </Text>
          </View>
        </TouchableNativeFeedback>
      </View>
    );
  }

  render() {
    const data = this.props.data;
    const messages = (data && data.messages || [])
      .reverse()
      .sort((a, b) => b.timestamp - a.timestamp);
    const items = messages.map((m, i) => (
      {
        ...m,
        hasTimestamp: i === 0 || i > 0 && m.authorId !== messages[i - 1].authorId,
      }
    ));
    const title = this.props.participant && this.props.participant.name || '';
    return (
      <View style={styles.container}>
        <Header
          title={title}
          centerComponent={this.renderHeaderTitle(title)}
          rightComponent={this.renderMuteButton()}
        />
        {this.props.loading && this.renderLoading()}
        {items.length > 0 && (
          <FlatList
            contentContainerStyle={styles.listContent}
            inverted={true}
            data={items}
            keyExtractor={this.getMsgKey}
            renderItem={this.renderItem}
          />) || !this.props.loading && this.renderEmpty()
        }
        <ChatInput
          style={styles.input}
          text={this.state.inputText}
          onInputTextChanged={this.onChangeText}
          onSendRequest={this.onSendRequest}
        />
      </View>
    );
  }
}

const mapStateToProps: (state: RootState, ownProps: OwnProps) => StateProps =
  (state, ownProps) => {
    const conversationId = ownProps.navigation.state.params.conversationId;
    const conversation = state.conversations.find((c) => c.id === conversationId);
    return {
      conversation,
      loading: !conversation,
      data: state.chats[conversationId],
      user: state.user,
      isMuted: conversation && conversation.muted && conversation.muted[state.user.body.id],
      participant: conversation && conversation[getOppositeRole(state.user.role)],
    };
  };

const mapDispatchToProps: (dispatch: Dispatch<RootState>, ownProps: OwnProps) => DispatchProps =
  (dispatch, ownProps) => {
    const conversationId = ownProps.navigation.state.params.conversationId;
    return {
      onToggleMute: (muted: boolean) =>
        dispatch(ChatActions.ToggleMuteConversationRequested(conversationId, muted)),
      onSendMessageRequest: (recipientId, msg) => dispatch(
        ChatActions.sendMessageRequested(conversationId, recipientId, msg)),
      onEmployerProfileRequested: (employerId: string) =>
        dispatch(NavActions.navigateToEmployerDetails(employerId)),
      onEmployeeProfileRequested: (employeeId: string) =>
        dispatch(NavActions.navigateToEmployeeDetails(employeeId)),
    };
  };

export const ChatRoom = connect(mapStateToProps, mapDispatchToProps)(ChatRoomComponent);

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  headerTitle: {
    marginLeft: -48,
  },
  listContent: {
    paddingHorizontal: 8,
  },
  input: {

  },
});
