import React from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import Modal from 'react-modal'
import isEqual from 'lodash/isEqual'
import cloneDeep from 'lodash/cloneDeep'
import ReusableImages from './reusable-images'
import ConfirmDelete from './confirm-delete'
import Admin from './../admin'
import Instance from './util/instance'
import { ConfirmDeleteModalStyles, ReusableImagesModalStyles } from './helpers/modal-styles'
import { fetchEntity, fetchEntities, createEntity, updateEntity, deleteEntity } from '../actions/index'
import { withExitPrompt } from './util/with-exit-prompt'

interface ObjectDetailsProps {
  errors: string[];
  deleteEntity: any;
  fetchEntity: any;
  fetchEntities: any;
  fields: any[];
  files: {};
  images: {};
  instances: any;
  object: any;
  objectSaved: any;
  templateEditable: boolean;
  templateId: number;
  templateName: string;
  updateEntity: any;
  contentDownloads: any[];
  eventSeries: any[];
  transcripts: any[];
}

interface ObjectDetailsState extends ComponentState {
  changedFields: any;
  fields: any[];
  files: any;
  images: any;
  instances: any;
  object: any;
  objectSaved: any;
  reusableImagesModalOpen?: boolean;
  reusableImagesFieldId: number;
  templateEditable?: boolean;
  templateId?: number;
  templateName?: string;
  contentDownloads: any[];
  eventSeries: any[];
  transcripts: any[];
}

class ObjectDetails extends React.Component<ObjectDetailsProps, ObjectDetailsState> {

  constructor(props) {
    super(props);
    this.state = {
      fetching: true,
      changedFields: {},
      object: {},
      objectSaved: {},
      fields: [],
      files: [],
      images: [],
      instances: {},
      errors: [],
      reusableImagesFieldId: null,
      contentDownloads: [],
      eventSeries: [],
      transcripts: []
    };
  }

  componentDidMount() {
    let pathDirectories = window.location.pathname.split('/');
    this.props.fetchEntity({
      id: pathDirectories[pathDirectories.length - 1],
      directory: "objekts",
      entityName: "objekt"
    }).then(() => {
      this.setState({
        fetching: false,
        object: this.props.object,
        objectSaved: cloneDeep(this.props.object),
        fields: this.props.fields,
        instances: this.props.instances,
        files: this.props.files,
        images: this.props.images,
        templateId: this.props.templateId,
        templateEditable: this.props.templateEditable,
        templateName: this.props.templateName,
        changedFields: {}
      }, () => {
        Instance.fetchAdditionalNeededData.call(this, { entityName: 'object', addingEntity: false });
      });
    });
  }

  clickSave() {
    this.setState({
      fetching: true,
      justSaved: true
    });
    this.props.updateEntity({
      id: this.state.object.id,
      directory: "objekts",
      entityName: "object",
      entity: this.state.object
    }).then(() => {
      this.setState({
        fetching: false,
        object: this.props.object,
        objectSaved: cloneDeep(this.props.object),
        changesToSave: false
      });
    }, () => {
      this.setState({
        fetching: false,
        errors: this.props.errors
      });
    });
  }

  confirmDelete() {
    this.props.deleteEntity({
      directory: "objekts",
      id: this.state.object.id,
      callback: () => {
        window.location.pathname = `/admin/templates/${this.state.templateId}/all`;
      }
    });
  }

  checkForChanges() {
    return !isEqual(this.state.object, this.state.objectSaved);
  }

  changeFieldArgs() {
    return {
      thing: "object",
      errorsArray: this.state.errors,
      changesFunction: this.checkForChanges.bind(this)
    }
  }

  selectReusableImage(uploadId, url) {
    let fieldId = this.state.reusableImagesFieldId;
    let object = this.state.object;
    object[fieldId] = uploadId;
    let images = this.state.images;
    let image = images[fieldId];
    let fieldName = this.state.fields.find(({ id }) => id === fieldId).name;
    Admin.removeDynamicFieldError(this.changeFieldArgs().errorsArray, fieldName);
    image['url'] = url;
    image['reusability'] = true;
    this.setState({
      object,
      images
    }, () => {
      this.setState({
        changesToSave: this.checkForChanges()
      });
    });
  }

  render() {
    return(
      <div id="object-details" className="component details-component">
        <h1>{ this.state.templateName } Details</h1>
        <div className="white-box">
          { Admin.renderSpinner(this.state.fetching) }
          { Admin.renderGrayedOut(this.state.fetching) }
          { Instance.renderFields.call(this, {
            fields: this.state.fields,
            entityName: 'object'
          }) }
          <a className={ "orange-button standard-button-width btn" + Admin.renderDisabledButtonClass(this.state.fetching || !this.state.changesToSave) } onClick={ this.clickSave.bind(this) }>
            { Admin.saveButtonText.call(this) }
          </a>
          <a href={ "/admin/templates/" + this.state.templateId + "/all" } className="link" id="view-all">View { this.state.templateName } List</a>
          { this.renderDeleteButton.call(this) }
        </div>
        <Modal isOpen={ this.state.deleteModalOpen } onRequestClose={ Admin.closeDeleteModal.bind(this) } contentLabel="Modal" style={ ConfirmDeleteModalStyles }>
          <ConfirmDelete entityId={ this.state.object.id } entityName="object" entityDirectory="objekts" closeModal={ Admin.closeDeleteModal.bind(this) } closeAndFetch={ Admin.closeDeleteModalAndFetch.bind(this) } delete={ this.confirmDelete.bind(this) } />
        </Modal>
        <Modal isOpen={ this.state.reusableImagesModalOpen } onRequestClose={ Admin.closeModals.bind(this) } contentLabel="Modal" style={ ReusableImagesModalStyles }>
          <ReusableImages
            entityName="object"
            closeModal={ Admin.closeModals.bind(this) }
            receiveReusableImageFunction={ Instance.selectReusableImage.bind(this) }
          />
        </Modal>
      </div>
    );
  }

  renderDeleteButton() {
    if (this.state.templateEditable) {
      return(
        <a className={ "delete-button" + Admin.renderDisabledButtonClass(this.state.fetching) } onClick={ Admin.changeState.bind(this, "deleteModalOpen", true) }>
          Delete
        </a>
      );
    } else {
      return null;
    }
  }

  componentDidUpdate() {
    $('.match-height-layout').matchHeight();
  }
}

const mapStateToProps = (reducers, props) => {
  return reducers.standardReducer;
};

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ fetchEntity, fetchEntities, createEntity, updateEntity, deleteEntity }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(withExitPrompt(ObjectDetails));
