import Inferno from 'inferno';
import { Component } from 'inferno';
import PropTypes from 'prop-types';
import marked from 'marked';

import { Modal } from '../../structure/Modal';

import { EditDictionaryForm } from './EditDictionaryForm';
import { EditLinguisticsForm } from './EditLinguisticsForm';
import { EditSettingsForm } from './EditSettingsForm';

const DISPLAY = {
  DETAILS: 1,
  LINGUISTICS: 2,
  SETTINGS: 3,
  ACTIONS: 4,
}

export class EditDictionaryModal extends Component {
  constructor (props) {
    super(props);

    PropTypes.checkPropTypes({
      name: PropTypes.string,
      specification: PropTypes.string,
      description: PropTypes.string,
      alphabeticalOrder: PropTypes.array,
      partsOfSpeech: PropTypes.array,
      details: PropTypes.object,
      settings: PropTypes.object,
      isLoggedIn: PropTypes.bool,
      updateDisplay: PropTypes.func,
    }, props, 'prop', 'EditDictionaryModal');

    this.state = {
      currentDisplay: DISPLAY.DETAILS,

      name: props.name,
      specification: props.specification,
      description: props.description,
      alphabeticalOrder: props.alphabeticalOrder.join('\n'),

      partsOfSpeech: props.partsOfSpeech.join('\n'),
      consonants: props.details.phonology.consonants.join(' '),
      vowels: props.details.phonology.vowels.join(' '),
      blends: props.details.phonology.blends.join(' '),
      onset: props.details.phonology.phonotactics.onset.join('\n'),
      nucleus: props.details.phonology.phonotactics.nucleus.join('\n'),
      coda: props.details.phonology.phonotactics.coda.join('\n'),
      exceptions: props.details.phonology.phonotactics.exceptions,
      orthographyNotes: props.details.orthography.notes,
      grammarNotes: props.details.grammar.notes,

      allowDuplicates: props.settings.allowDuplicates,
      caseSensitive: props.settings.caseSensitive,
      sortByDefinition: props.settings.sortByDefinition,
      isComplete: props.settings.isComplete,
      isPublic: props.settings.isPublic,

      hasChanged: false,
    }

    this.modal = null;
  }

  hasChanged () {
    return (
      this.state.name != this.props.name
      || this.state.specification != this.props.specification
      || this.state.description != this.props.description
      || this.state.partsOfSpeech != this.props.partsOfSpeech.join('\n')
    );
  }

  toggleDisplay (display) {
    this.setState({
      currentDisplay: display,
    });
  }

  displaySection () {
    let displayJSX;

    switch(this.state.currentDisplay) {
      case DISPLAY.DETAILS : {
        displayJSX = (
          <EditDictionaryForm
            editDictionaryModal={ this }
            name={ this.state.name }
            specification={ this.state.specification }
            description={ this.state.description }
            alphabeticalOrder={ this.state.alphabeticalOrder }
          />
        );
        break;
      }

      case DISPLAY.LINGUISTICS : {
        displayJSX = (
          <EditLinguisticsForm
            editDictionaryModal={ this }
            partsOfSpeech={ this.state.partsOfSpeech }
            consonants={ this.state.consonants }
            vowels={ this.state.vowels }
            blends={ this.state.blends }
            onset={ this.state.onset }
            nucleus={ this.state.nucleus }
            coda={ this.state.coda }
            exceptions={ this.state.exceptions }
            orthographyNotes={ this.state.orthographyNotes }
            grammarNotes={ this.state.grammarNotes }
          />
        );
        break;
      }

      case DISPLAY.SETTINGS : {
        displayJSX = (
          <EditSettingsForm
            editDictionaryModal={ this }
            allowDuplicates={ this.state.allowDuplicates }
            caseSensitive={ this.state.caseSensitive }
            sortByDefinition={ this.state.sortByDefinition }
            isComplete={ this.state.isComplete }
            specification={ this.state.specification }
            isLoggedIn={ this.props.isLoggedIn }
            isPublic={ this.state.isPublic }
          />
        );
        break;
      }

      case DISPLAY.ACTIONS : {
        displayJSX = (
          <div class="content">
            <p>Actions like import, export, delete, etc.</p>
          </div>
        );
      }
    }

    return (
      <div className='box'>
        { displayJSX }
      </div>
    );
  }

  save (callback = () => {}) {
    const updatedDetails = {};

    if (this.state.name !== this.props.name) {
      updatedDetails['name'] = this.state.name.trim();
    }

    if (this.state.specification !== this.props.specification) {
      updatedDetails['specification'] = this.state.specification.trim();
    }

    if (this.state.description !== this.props.description) {
      updatedDetails['description'] = this.state.description;
    }

    if (this.state.alphabeticalOrder !== this.props.alphabeticalOrder.join('\n')) {
      updatedDetails['alphabeticalOrder'] = this.state.alphabeticalOrder.split('\n')
        .filter((value) => { return value !== '' })
        .map((value) => { return value.trim() });
    }

    if (this.state.partsOfSpeech !== this.props.partsOfSpeech.join('\n')) {
      updatedDetails['partsOfSpeech'] = this.state.partsOfSpeech.split('\n')
        .filter((value) => { return value !== '' })
        .map((value) => { return value.trim() });
    }

    if (this.state.alphabeticalOrder !== this.props.alphabeticalOrder.join('\n')) {
      updatedDetails['alphabeticalOrder'] = this.state.alphabeticalOrder.split('\n')
        .filter((value) => { return value !== '' })
        .map((value) => { return value.trim() });
    }

    if (this.state.consonants !== this.props.details.phonology.consonants.join(' ')) {
      updatedDetails['consonants'] = this.state.consonants.split(' ')
        .filter((value) => { return value !== '' })
        .map((value) => { return value.trim() });
    }

    if (this.state.vowels !== this.props.details.phonology.vowels.join(' ')) {
      updatedDetails['vowels'] = this.state.vowels.split(' ')
        .filter((value) => { return value !== '' })
        .map((value) => { return value.trim() });
    }

    if (this.state.blends !== this.props.details.phonology.blends.join(' ')) {
      updatedDetails['blends'] = this.state.blends.split(' ')
        .filter((value) => { return value !== '' })
        .map((value) => { return value.trim() });
    }

    if (this.state.onset !== this.props.details.phonology.phonotactics.onset.join('\n')) {
      updatedDetails['onset'] = this.state.onset.split('\n')
        .filter((value) => { return value !== '' })
        .map((value) => { return value.trim() });
    }

    if (this.state.nucleus !== this.props.details.phonology.phonotactics.nucleus.join('\n')) {
      updatedDetails['nucleus'] = this.state.nucleus.split('\n')
        .filter((value) => { return value !== '' })
        .map((value) => { return value.trim() });
    }

    if (this.state.coda !== this.props.details.phonology.phonotactics.coda.join('\n')) {
      updatedDetails['coda'] = this.state.coda.split('\n')
        .filter((value) => { return value !== '' })
        .map((value) => { return value.trim() });
    }

    if (this.state.exceptions !== this.props.details.phonology.phonotactics.exceptions) {
      updatedDetails['exceptions'] = this.state.exceptions;
    }

    if (this.state.orthographyNotes !== this.props.details.orthography.notes) {
      updatedDetails['orthographyNotes'] = this.state.orthographyNotes;
    }

    if (this.state.grammarNotes !== this.props.details.grammar.notes) {
      updatedDetails['grammarNotes'] = this.state.grammarNotes;
    }

    if (this.state.allowDuplicates !== this.props.settings.allowDuplicates) {
      updatedDetails['allowDuplicates'] = this.state.allowDuplicates;
    }

    if (this.state.caseSensitive !== this.props.settings.caseSensitive) {
      updatedDetails['caseSensitive'] = this.state.caseSensitive;
    }

    if (this.state.sortByDefinition !== this.props.settings.sortByDefinition) {
      updatedDetails['sortByDefinition'] = this.state.sortByDefinition;
    }

    if (this.state.isComplete !== this.props.settings.isComplete) {
      updatedDetails['isComplete'] = this.state.isComplete;
    }

    if (this.state.isPublic !== this.props.settings.isPublic) {
      updatedDetails['isPublic'] = this.state.isPublic;
    }

    // console.log(updatedDetails);

    this.props.updater.updateDictionaryDetails(updatedDetails)
      .then(() => {
        this.setState({ hasChanged: false }, () => {
          // If setting that alters word display is changed, update the display.
          if (updatedDetails.hasOwnProperty('sortByDefinition')) {
            this.props.updateDisplay(callback);
          }
        });
      })
      .catch(errorMessage => {
        console.error(errorMessage);
      });
  }

  render () {
    const { currentDisplay, hasChanged } = this.state;
    const { specification, settings, isLoggedIn } = this.props;

    return (
      <Modal title={ `Edit ${ specification }` }
        buttonText={ `Edit ${ specification }` }
        footerAlign='right'
        footerContent={
          (
            <div>
              <button className='button is-success'
                disabled={ !hasChanged }
                onClick={ this.save.bind(this) }
              >
                Save
              </button>
              <button className='button'
                disabled={ !hasChanged }
                onClick={ () => this.save(this.modal.hide())}
              >
                Save & Close
              </button>
            </div>
          )
        }
        ref={(modal) => this.modal = modal}
      >

        {!settings.isComplete
          ? [(
              <div className='tabs'>
                <ul>
                  <li className={ (currentDisplay === DISPLAY.DETAILS) ? 'is-active' : null }>
                    <a onClick={ this.toggleDisplay.bind(this, DISPLAY.DETAILS) }>
                      Details
                    </a>
                  </li>
                  <li className={ (currentDisplay === DISPLAY.LINGUISTICS) ? 'is-active' : null }>
                    <a onClick={ this.toggleDisplay.bind(this, DISPLAY.LINGUISTICS) }>
                      Linguistics
                    </a>
                  </li>
                  <li className={ (currentDisplay === DISPLAY.SETTINGS) ? 'is-active' : null }>
                    <a onClick={ this.toggleDisplay.bind(this, DISPLAY.SETTINGS) }>
                      Settings
                    </a>
                  </li>
                  <li className={ (currentDisplay === DISPLAY.ACTIONS) ? 'is-active' : null }>
                    <a onClick={ this.toggleDisplay.bind(this, DISPLAY.ACTIONS) }>
                      Actions
                    </a>
                  </li>
                </ul>
              </div>
            ),
            this.displaySection(),
          ] : (
            <div className='columns'>

              <div className='column has-text-centered'>
                { specification } marked complete&mdash;editing has been disabled.<br />
                <a className='button is-warning is-small'
                  onClick={() => {
                    this.setState({ isComplete: false, currentDisplay: DISPLAY.SETTINGS }, () => {
                      this.save();
                    })
                  }}>
                  Mark it incomplete
                </a>
              </div>

              {isLoggedIn
               && (
                  <div className='column has-text-centered'>
                    Your dictionary is <strong>{ settings.isPublic ? 'Public' : 'Private'}</strong>
                    {settings.isPublic
                      && (
                        [
                          ' You can view it at',
                          <br />,
                          <a className='button is-text is-small'
                            onClick={() => console.log('set up copying to clipboard')}>
                            PUBLIC_LINK
                          </a>,
                        ]
                      )}
                    <br />
                    <a className='button is-small'
                      onClick={() => {
                        this.setState({ isPublic: !settings.isPublic }, () => {
                          this.save();
                        })
                      }}>
                      Mark it { settings.isPublic ? 'Private' : 'Public'}
                    </a>
                  </div>
                )}

            </div>
          )
        }
      </Modal>
    );
  }
}
