import * as React from 'react';
import { Component, Styles, Text, Types, View } from 'reactxp';
import { colors } from '../../config.json';
import { TunnelState } from '../../shared/daemon-rpc-types';
import { cities, countries, messages, relayLocations } from '../../shared/gettext';
import ConnectionPanelContainer from '../containers/ConnectionPanelContainer';
import * as AppButton from './AppButton';
import SecuredLabel, { SecuredDisplayStyle } from './SecuredLabel';

interface ITunnelControlProps {
  tunnelState: TunnelState;
  selectedRelayName: string;
  city?: string;
  country?: string;
  onConnect: () => void;
  onDisconnect: () => void;
  onSelectLocation: () => void;
}

const styles = {
  body: Styles.createViewStyle({
    paddingTop: 0,
    paddingLeft: 24,
    paddingRight: 24,
    paddingBottom: 0,
    marginTop: 176,
    flex: 1,
  }),
  footer: Styles.createViewStyle({
    flex: 0,
    paddingBottom: 16,
    paddingLeft: 24,
    paddingRight: 24,
  }),
  wrapper: Styles.createViewStyle({
    flex: 1,
  }),
  switch_location_button: Styles.createViewStyle({
    marginBottom: 16,
  }),
  status_security: Styles.createTextStyle({
    fontFamily: 'Open Sans',
    fontSize: 16,
    fontWeight: '800',
    lineHeight: 22,
    marginBottom: 4,
  }),
  status_location: Styles.createTextStyle({
    flexDirection: 'column',
    marginBottom: 4,
  }),
  status_location_text: Styles.createTextStyle({
    fontFamily: 'DINPro',
    fontSize: 34,
    lineHeight: 36,
    fontWeight: '900',
    overflow: 'hidden',
    letterSpacing: -0.9,
    color: colors.white,
  }),
};

export default class TunnelControl extends Component<ITunnelControlProps> {
  public render() {
    const Location = ({ children }: { children?: React.ReactNode }) => (
      <View style={styles.status_location}>{children}</View>
    );
    const City = () => (
      <Text style={styles.status_location_text}>
        {this.props.city
          ? relayLocations.gettext(this.props.city) ||
            cities.gettext(this.props.city) ||
            this.props.city
          : undefined}
      </Text>
    );
    const Country = () => (
      <Text style={styles.status_location_text}>
        {this.props.country
          ? countries.gettext(this.props.country) || this.props.country
          : undefined}
      </Text>
    );

    const SwitchLocation = () => {
      return (
        <AppButton.TransparentButton
          style={styles.switch_location_button}
          onPress={this.props.onSelectLocation}>
          {messages.pgettext('tunnel-control', 'Switch location')}
        </AppButton.TransparentButton>
      );
    };

    const SelectedLocation = () => (
      <AppButton.TransparentButton
        style={styles.switch_location_button}
        onPress={this.props.onSelectLocation}>
        <AppButton.Label>{this.props.selectedRelayName}</AppButton.Label>
        <AppButton.Icon height={12} width={7} source="icon-chevron" />
      </AppButton.TransparentButton>
    );

    const Connect = () => (
      <AppButton.GreenButton onPress={this.props.onConnect}>
        {messages.pgettext('tunnel-control', 'Secure my connection')}
      </AppButton.GreenButton>
    );

    const Disconnect = () => (
      <AppButton.RedTransparentButton onPress={this.props.onDisconnect}>
        {messages.pgettext('tunnel-control', 'Disconnect')}
      </AppButton.RedTransparentButton>
    );

    const Cancel = () => (
      <AppButton.RedTransparentButton onPress={this.props.onDisconnect}>
        {messages.pgettext('tunnel-control', 'Cancel')}
      </AppButton.RedTransparentButton>
    );

    const Secured = ({ displayStyle }: { displayStyle: SecuredDisplayStyle }) => (
      <SecuredLabel style={styles.status_security} displayStyle={displayStyle} />
    );
    const Footer = ({ children }: { children: React.ReactNode }) => (
      <View style={styles.footer}>{children}</View>
    );

    let state = this.props.tunnelState.state;

    switch (this.props.tunnelState.state) {
      case 'blocked':
        switch (this.props.tunnelState.details.reason) {
          case 'set_firewall_policy_error':
            state = 'disconnected';
            break;
          default:
            state = 'blocked';
            break;
        }
        break;

      case 'disconnecting':
        switch (this.props.tunnelState.details) {
          case 'block':
            state = 'blocked';
            break;
          case 'reconnect':
            state = 'connecting';
            break;
          default:
            state = 'disconnecting';
            break;
        }
        break;
    }

    switch (state) {
      case 'connecting':
        return (
          <Wrapper>
            <Body>
              <Secured displayStyle={SecuredDisplayStyle.securing} />
              <Location>
                <City />
                <Country />
              </Location>
              <ConnectionPanelContainer />
            </Body>
            <Footer>
              <SwitchLocation />
              <Cancel />
            </Footer>
          </Wrapper>
        );
      case 'connected':
        return (
          <Wrapper>
            <Body>
              <Secured displayStyle={SecuredDisplayStyle.secured} />
              <Location>
                <City />
                <Country />
              </Location>
              <ConnectionPanelContainer />
            </Body>
            <Footer>
              <SwitchLocation />
              <Disconnect />
            </Footer>
          </Wrapper>
        );

      case 'blocked':
        return (
          <Wrapper>
            <Body>
              <Secured displayStyle={SecuredDisplayStyle.blocked} />
            </Body>
            <Footer>
              <SwitchLocation />
              <Cancel />
            </Footer>
          </Wrapper>
        );

      case 'disconnecting':
        return (
          <Wrapper>
            <Body>
              <Secured displayStyle={SecuredDisplayStyle.secured} />
              <Location>
                <Country />
              </Location>
            </Body>
            <Footer>
              <SelectedLocation />
              <Connect />
            </Footer>
          </Wrapper>
        );

      case 'disconnected':
        return (
          <Wrapper>
            <Body>
              <Secured displayStyle={SecuredDisplayStyle.unsecured} />
              <Location>
                <Country />
              </Location>
            </Body>
            <Footer>
              <SelectedLocation />
              <Connect />
            </Footer>
          </Wrapper>
        );

      default:
        throw new Error(`Unknown TunnelState: ${this.props.tunnelState}`);
    }
  }
}

interface IContainerProps {
  children?: Types.ReactNode;
}

class Wrapper extends Component<IContainerProps> {
  public render() {
    return <View style={styles.wrapper}>{this.props.children}</View>;
  }
}

class Body extends Component<IContainerProps> {
  public render() {
    return <View style={styles.body}>{this.props.children}</View>;
  }
}
