import React, { Component } from 'react';
import _ from 'lodash';
import FontAwesome from 'react-fontawesome';
import { connect } from 'react-redux';
import { withRouter } from 'react-router';

import { stringActions } from '../apis';
import { jobStatusesUpdate, jobStatusesLoaded, jobHideSeenUpdate, jobHideSeenLoaded } from '../actions';
import { STATUS_NOT_ACTIONED, STATUS_IN_PROGRESS, STATUS_COMPLETED } from '../helper';
import { PlussCore } from '../feature.config';
import { values } from '../values.config';

const { Session, Components, Colours } = PlussCore;

class Configuration extends Component {
  constructor(props) {
    super(props);
    this.state = {
      success: false,
      submitting: false,
      selectedStatusIndex: -1,
      showStatusPopup: false,
      statusLabel: '',
      statusCategory: STATUS_NOT_ACTIONED,
      statusColour: '',
      fetchingStatusTypes: true,
      statusTypes: this.props.statusTypes,
      fetchingHideSeen: true,
      hideSeen: this.props.hideSeen,
    };
  }

  UNSAFE_componentWillMount() {
    Session.checkLoggedIn(this);
  }

  componentDidMount() {
    if (!Session.validateAccess(this.props.auth.site, 'featurePicker', this.props.auth, true)) {
      this.props.history.push('/mastermenu');
    } else {
      this.props.jobStatusesUpdate(this.props.auth.site, (statusTypes) => this.setState({ statusTypes, fetchingStatusTypes: false }));
      this.props.jobHideSeenUpdate(this.props.auth.site, (hideSeen) => this.setState({ hideSeen, fetchingHideSeen: false }));
    }
  }

  isStatusValid = (statusLabel, statusCategory, statusColour) => {
    if (_.isEmpty(statusLabel)) return false;
    if (_.isEmpty(statusCategory)) return false;
    if (_.isEmpty(statusColour)) return false;

    return true;
  };

  validateForm() {
    const { submitting, statusTypes } = this.state;
    if (submitting) return false;

    // Validate statuses
    const statusesValid = statusTypes.map((status) => {
      const { text, category, color } = status;
      return this.isStatusValid(text, category, color);
    });
    if (!statusesValid.every((valid) => valid)) return false;

    return true;
  }

  onMoveStatus = (index, up = true) => {
    if (this.state.fetchingStatusTypes) return;

    const statusTypes = _.cloneDeep(this.state.statusTypes);

    if (up && index > 0) {
      // Moving up
      [statusTypes[index - 1], statusTypes[index]] = [statusTypes[index], statusTypes[index - 1]];
    } else if (index < statusTypes.length - 1) {
      // Moving down
      [statusTypes[index], statusTypes[index + 1]] = [statusTypes[index + 1], statusTypes[index]];
    }
    // Reset order
    statusTypes.forEach((status, index) => (status.order = index));

    this.setState({ statusTypes });
  };

  onEditStatus = (index) => {
    if (this.state.fetchingStatusTypes) return;

    const status = this.state.statusTypes[index];

    this.setState({
      showWarnings: false,
      showStatusPopup: true,
      selectedStatusIndex: index,
      statusLabel: status.text,
      statusCategory: status.category,
      statusColour: status.color,
    });
  };

  onDeleteStatus = (index) => {
    if (this.state.fetchingStatusTypes) return;

    const statusTypes = _.cloneDeep(this.state.statusTypes);
    statusTypes.splice(index, 1);

    this.setState({ statusTypes });
  };

  onAddStatus = () => {
    const defaultStatus = this.props.statusTypes.find((s) => s.category === STATUS_NOT_ACTIONED);
    this.setState({
      showWarnings: false,
      showStatusPopup: true,
      selectedStatusIndex: -1,
      statusLabel: '',
      statusCategory: STATUS_NOT_ACTIONED,
      statusColour: defaultStatus.color,
    });
  };

  onSaveStatus = () => {
    const { selectedStatusIndex, statusLabel, statusCategory, statusColour } = this.state;
    const statusTypes = _.cloneDeep(this.state.statusTypes);

    if (selectedStatusIndex < 0) {
      statusTypes.push({
        text: statusLabel,
        order: statusTypes.length,
        color: statusColour,
        category: statusCategory,
      });
    } else {
      const status = statusTypes[selectedStatusIndex];
      status.text = statusLabel;
      status.color = statusColour;
      status.category = statusCategory;
    }

    this.setState({ statusTypes, showStatusPopup: false });
  };

  onHideStatusPopup = () => {
    if (this.state.submitting) return;

    this.setState({ showStatusPopup: false });
  };

  onHandleChange = (event) => {
    var stateChange = {};
    stateChange[event.target.getAttribute('id')] = event.target.value;
    this.setState(stateChange);
  };

  onToggleDisableSeen = () => {
    if (this.state.fetchingHideSeen) return;

    this.setState({ hideSeen: !this.state.hideSeen });
  };

  onSaveConfig = () => {
    if (!this.validateForm()) return;

    this.setState({ success: false, submitting: true }, async () => {
      try {
        const { statusTypes, hideSeen } = this.state;
        await stringActions.setString(this.props.auth.site, values.stringConfigJobStatus, statusTypes);
        await stringActions.setString(this.props.auth.site, values.stringConfigHideSeen, hideSeen);
        this.props.jobStatusesLoaded(statusTypes);
        this.props.jobHideSeenLoaded(hideSeen);

        this.setState({ success: true });
      } catch (error) {
        console.log('onSaveConfig - error', error);
        this.setState({ success: false });
      } finally {
        this.setState({ submitting: false });
      }
    });
  };

  renderStatuses() {
    const { statusTypes } = this.state;
    return (
      <div>
        <p className="fontMedium fontSize-36 text-dark">Statuses</p>
        <div style={styles.statusCategoryHeading}>
          <span className="fontMedium fontSize-16 text-bold">Status Category</span>
        </div>
        {statusTypes.map((status, index) => {
          return (
            <div key={`${status.text}_${index}`} style={styles.statusTypeContainer}>
              <div key={status.text} className="statusLabel" style={{ ...styles.statusTextContainer, backgroundColor: status.color }}>
                <span className="statusLabel_text">{status.text}</span>
              </div>
              <div style={styles.statusCategoryContainer}>
                <span className="fontMedium fontSize-16 text-dark">{status.category}</span>
              </div>
              <FontAwesome
                style={{ ...styles.statusIcon, visibility: index === 0 ? 'hidden' : 'visible' }}
                name={'arrow-up'}
                onClick={() => this.onMoveStatus(index, true)}
              />
              <FontAwesome
                style={{ ...styles.statusIcon, visibility: index === statusTypes.length - 1 ? 'hidden' : 'visible' }}
                name={'arrow-down'}
                onClick={() => this.onMoveStatus(index, false)}
              />
              <FontAwesome style={{ ...styles.statusIcon }} name="pencil" onClick={() => this.onEditStatus(index)} />
              <FontAwesome style={{ ...styles.statusIcon }} name="minus-circle" onClick={() => this.onDeleteStatus(index)} />
            </div>
          );
        })}
        <div onClick={this.onAddStatus} style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', marginTop: 16 }}>
          <Components.P60Icon className="addoption_plus" icon="add" style={{ fontSize: 12 }} />
          <p className="addoption_text">Add another status</p>
        </div>
      </div>
    );
  }

  renderOtherOptions() {
    return (
      <div className="marginTop-55">
        <p className="fontMedium fontSize-36 text-dark">Other options</p>
        <Components.CheckBox
          label={`Disable whether a request has been "Seen" and prevent that from being surfaced to the App user`}
          isActive={this.state.hideSeen}
          onChange={this.onToggleDisableSeen}
        />
      </div>
    );
  }

  renderSubmit() {
    if (this.state.submitting) {
      return <Components.Button buttonType="secondary">Saving...</Components.Button>;
    }
    return (
      <Components.Button inline buttonType="primary" onClick={this.onSaveConfig} isActive={this.validateForm()}>
        Save
      </Components.Button>
    );
  }

  renderSuccess() {
    if (!this.state.success) return null;
    return <span style={{ ...styles.savedText, color: Colours.COLOUR_GREEN }}>Saved</span>;
  }

  renderNewStatusPopup() {
    const { submitting, showStatusPopup, showWarnings, selectedStatusIndex, statusLabel, statusCategory, statusColour } = this.state;
    if (!showStatusPopup) return null;

    const canSave = !submitting && this.isStatusValid(statusLabel, statusCategory, statusColour);
    return (
      <Components.Popup
        maxWidth={800}
        minWidth={450}
        hasPadding
        buttons={[
          {
            type: 'primaryAction',
            onClick: this.onSaveStatus,
            isActive: canSave,
            isActive: true,
            text: submitting ? 'Saving...' : 'Save',
            className: 'popupButton',
          },
          {
            type: 'outlinedAction',
            onClick: this.onHideStatusPopup,
            isActive: !submitting,
            text: 'Cancel',
            className: 'popupButton',
          },
        ]}
        onClose={this.onHideStatusPopup}
        title={selectedStatusIndex < 0 ? 'New Status' : 'Edit Status'}
      >
        <Components.GenericInput
          id="statusLabel"
          type="text"
          label="Label"
          placeholder="Status label"
          value={statusLabel}
          onChange={this.onHandleChange}
          isRequired
          isValid={() => !_.isEmpty(statusLabel)}
          showError={() => showWarnings && _.isEmpty(statusLabel)}
          alwaysShowLabel
          className="marginBottom-20"
        />
        <Components.RadioButton
          label="Status Category"
          subLabel={
            <div className="marginBottom-16">
              <div className="marginBottom-4">{'This is used to categorise statuses for filtering and analytics purposes'}</div>
              <div className="text-bold">{'This status is considered'}</div>
            </div>
          }
          className="marginBottom-20"
          rowStyle={{ flexDirection: 'column' }}
          buttonStyle={{ marginBottom: 8 }}
          isActive={statusCategory || null}
          options={[
            {
              Label: STATUS_NOT_ACTIONED,
              Value: STATUS_NOT_ACTIONED,
              onChange: () => this.setState({ statusCategory: STATUS_NOT_ACTIONED }),
            },
            { Label: STATUS_IN_PROGRESS, Value: STATUS_IN_PROGRESS, onChange: () => this.setState({ statusCategory: STATUS_IN_PROGRESS }) },
            { Label: STATUS_COMPLETED, Value: STATUS_COMPLETED, onChange: () => this.setState({ statusCategory: STATUS_COMPLETED }) },
          ]}
        />

        <Components.ColourOptions
          options={['vibrant', 'picker']}
          defaultTab="vibrant"
          value={statusColour}
          onColourSelected={(statusColour) => this.setState({ statusColour })}
        />
        <div className="marginTop-24">
          <div className="fieldLabel marginBottom-4">Preview</div>
          <Components.Tag text={this.state.statusLabel} style={{ backgroundColor: statusColour, borderColor: statusColour }} />
        </div>
      </Components.Popup>
    );
  }

  render() {
    return (
      <div style={{ minWidth: '100%' }}>
        {this.renderStatuses()}
        {this.renderOtherOptions()}
        <div style={{ paddingTop: 24, paddingBottom: 24 }}>
          {this.renderSubmit()}
          {this.renderSuccess()}
        </div>
        {this.renderNewStatusPopup()}
      </div>
    );
  }
}

const styles = {
  statusCategoryHeading: {
    marginLeft: 130,
    width: 160,
    textAlign: 'center',
    marginBottom: 12,
  },
  statusTypeContainer: {
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 20,
  },
  statusTextContainer: {
    width: 130,
  },
  statusCategoryContainer: {
    width: 160,
    textAlign: 'center',
  },
  statusIcon: {
    cursor: 'pointer',
    fontSize: 20,
    padding: 5,
    marginLeft: 10,
    color: Colours.COLOUR_BRANDING_ACTION,
    visibility: 'visible',
  },
  savedText: {
    fontSize: 14,
    lineHeight: '33px',
    marginLeft: 15,
  },
};

const mapStateToProps = (state) => {
  const { auth } = state;
  return {
    auth,
    statusTypes: state[values.reducerKey].jobstatuses,
    hideSeen: state[values.reducerKey].hideSeen,
  };
};

export default connect(mapStateToProps, { jobStatusesUpdate, jobStatusesLoaded, jobHideSeenUpdate, jobHideSeenLoaded })(
  withRouter(Configuration),
);
