import React from "react"
import { connect } from "react-redux"
import { bindActionCreators } from "redux"
import ChangeCase from "change-case"
import cloneDeep from 'lodash/cloneDeep'
import Admin from "./../admin"
import Tools from "./../../app/assets/javascripts/teachable/tools"
import { fetchDataForNew, createEntity } from "../actions/index"

let entityNamePlural;
let directory;

interface NewEntityProps {
  beforeCreate: any;
  buttonText?: string;
  callback: any;
  createEntity: any;
  duration: any;
  entities?: any[];
  entity?: any;
  entityName: string;
  entityNamePlural?: string;
  errors?: string[];
  fetchData: string[];
  fetchDataForNew: any;
  frontEndCallback: any;
  initialEntity: any;
  redirect: boolean;
  staticState: any;
}

interface NewEntityState {
  errors?: string[];
  fetching: boolean;
}

class NewEntity extends React.Component<NewEntityProps, NewEntityState> {

  constructor(props) {
    super(props);
    entityNamePlural = this.props.entityNamePlural || `${this.props.entityName}s`;
    directory = Tools.convertToUnderscore(entityNamePlural);
    let initialState = {
      fetching: !!this.props.fetchData,
      [this.props.entityName]: cloneDeep(this.props.initialEntity),
      errors: []
    };
    this.state = Object.assign(initialState, this.props.staticState);
  }

  componentDidMount() {
    if (this.props.fetchData) {
      this.props.fetchDataForNew({ directory }).then(() => {
        let entity = cloneDeep(this.state[this.props.entityName]);
        let obj = { fetching: false };
        this.props.fetchData.forEach((arrayName) => {
          obj[arrayName] = this.props[arrayName];
          if (this.props[arrayName][0].id) { // <-- eventually make this configurable
            entity[arrayName.slice(0, -1)] = this.props[arrayName][0].id;
          }
        })
        obj[this.props.entityName] = entity;
        this.setState(obj, () => {
          Admin.setUpNiceSelect({ selector: '.admin-modal select', func: Admin.changeField.bind(this, this.changeFieldArgs()) });
        });
      });
    } else {
      Admin.setUpNiceSelect({ selector: '.admin-modal select', func: Admin.changeField.bind(this, this.changeFieldArgs()) });
    }
  }

  clickAdd(e) {
    e.preventDefault();
    let entity = this.state[this.props.entityName];
    if (this.props.beforeCreate) {
      entity = this.props.beforeCreate.call(this, cloneDeep(entity));
    }
    if (this.props.frontEndCallback) {
      this.props.frontEndCallback(entity);
    } else {
      this.setState({
        fetching: true
      });
      this.props.createEntity({
        directory,
        entityName: this.props.entityName,
        entity
      }).then(() => {
        if (this.props.redirect) {
          window.location.pathname = `/admin/${directory}/${this.props[this.props.entityName].id}`;
        } else {
          this.props.callback(this.props[entityNamePlural]);
        }
      }, () => {
        this.setState({
          fetching: false,
          errors: this.props.errors
        });
      });
    }
  }

  changeFieldArgs() {
    return {
      allErrors: Admin.errors,
      errorsArray: this.state.errors,
      thing: this.props.entityName
    };
  }

  render() {
    return(
      <div className="admin-modal">
        <div id="new-entity" className="component details-component">
          <div className="white-box">
            { Admin.renderSpinner(this.state.fetching) }
            { Admin.renderGrayedOut(this.state.fetching) }
            { this.renderFields() }
            <a className={ "orange-button" + Admin.renderDisabledButtonClass(this.state.fetching) } onClick={ this.clickAdd.bind(this) }>{ this.props.buttonText || `Add ${ChangeCase.titleCase(this.props.entityName)}` }</a>
          </div>
        </div>
      </div>
    );
  }

  renderFields() {
    switch (this.props.entityName) {
      case "blogPost":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 12, entity: "blogPost", property: "title" }) }
            { Admin.renderField.bind(this)({ columnWidth: 10, entity: "blogPost", property: "titleText" }) }
            { Admin.renderField.bind(this)({ columnWidth: 2, entity: "blogPost", property: "date" }) }
          </div>
        ]);
      case "banner":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 6, entity: "banner", property: "name" }) }
            { Admin.renderDropDown.bind(this)({
              columnWidth: 6,
              entity: "banner",
              property: "bannerKey",
              columnHeader: "Type",
              includeBlank: true,
              limit: 3,
              optionLabel: "name",
              optionValue: "name"
            }) }
          </div>
        ]);
      case "customSlug":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 12, entity: "customSlug", property: "slug", columnHeader: "Custom Slug" }) }
          </div>
        ]);
      case "contentDownload":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 12, entity: "contentDownload", property: "name" }) }
            { Admin.renderDropDown.bind(this)({
              columnWidth: 4,
              entity: "contentDownload",
              property: "contentCategoryId",
              columnHeader: "Category",
              limit: 3,
              optionLabel: "name",
              optionValue: "id"
            }) }
            { Admin.renderDropDown.bind(this)({
              columnWidth: 4,
              entity: "contentDownload",
              property: "contentFunnelStageId",
              columnHeader: "Funnel Stage",
              limit: 3,
              optionLabel: "name",
              optionValue: "id"
            }) }
            { Admin.renderField.bind(this)({ columnWidth: 4, entity: "contentDownload", property: "contentScore" }) }
          </div>
        ]);
      case "eventSeries":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 12, entity: "eventSeries", property: "name" }) }
          </div>
        ]);
      case "feature":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 12, entity: "feature", property: "text" }) }
          </div>
        ]);
      case "page":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 6, entity: "page", property: "name" }) }
            { Admin.renderField.bind(this)({ columnWidth: 6, entity: "page", property: "url" }) }
          </div>,
          <div key="2" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 12, entity: "page", property: "titleText" }) }
          </div>
        ]);
      case "param":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 12, entity: "param", property: "text", autoFormat: Admin.hyphenFormat }) }
          </div>
        ]);
      case "partial":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 12, entity: "partial", property: "name" }) }
          </div>
        ]);
      case "redirect":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 6, entity: "redirect", property: "url" }) }
            { Admin.renderField.bind(this)({ columnWidth: 6, entity: "redirect", property: "redirect" }) }
          </div>
        ]);
      case "template":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 12, entity: "template", property: "name" }) }
          </div>
        ]);
      case "tooltip":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 12, entity: "tooltip", property: "text" }) }
          </div>
        ]);
      case "user":
        return([
          <div key="1" className="row">
            { Admin.renderImageField.bind(this)({ columnWidth: 4, entity: "user", property: "imageId", imageUrlProperty: "imageUrl", columnHeader: "Profile Picture", createImageRecord: true }) }
          </div>,
          <div key="2" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 4, entity: "user", property: "name" }) }
            { Admin.renderField.bind(this)({ columnWidth: 4, entity: "user", property: "email" }) }
            { Admin.renderField.bind(this)({ columnWidth: 4, entity: "user", property: "password" }) }
          </div>,
          <div key="3" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 4, entity: "user", property: "title" }) }
            { Admin.renderDropDown.bind(this)({
              columnWidth: 4,
              entity: "user",
              property: "teamId",
              columnHeader: "Team ID",
              limit: 3,
              optionLabel: "name",
              optionValue: "id"
            }) }
            { Admin.renderDropDown.bind(this)({
              columnWidth: 4,
              entity: "user",
              property: "permissionId",
              columnHeader: "Permission ID",
              limit: 3,
              optionLabel: "name",
              optionValue: "id"
            }) }
          </div>
        ]);
      case "webinar":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 3, columnHeader: "Name (Internal)", entity: "webinar", property: "name", placeholder: "7 Steps" }) }
            { Admin.renderField.bind(this)({ columnWidth: 3, entity: "webinar", property: "url", placeholder: "7-steps-to-launch" }) }
            { Admin.renderField.bind(this)({ columnWidth: 6, entity: "webinar", property: "title", placeholder: "7 steps to launch your own profitable online course" }) }
          </div>,
          <div key="2" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 3, entity: "webinar", property: "time", columnHeader: "Date/Time", placeholder: "11/5/1605 2:00pm" }) }
            { Admin.renderField.bind(this)({ columnWidth: 3, entity: "webinar", property: "time2", columnHeader: "Date/Time 2 (Optional)", placeholder: "11/5/1605 2:00pm" }) }
          </div>
        ]);
      case "webinarOffer":
        return([
          <div key="1" className="row">
            { Admin.renderField.bind(this)({ columnWidth: 6, entity: "webinarOffer", property: "title" }) }
            { Admin.renderField.bind(this)({ columnWidth: 6, entity: "webinarOffer", property: "description" }) }
          </div>,
          <div key="2" className="row">
            { Admin.renderDropDown.bind(this)({
              columnWidth: 2,
              entity: "webinarOffer",
              property: "anchorPoint",
              optionLabel: "text",
              optionValue: "value",
              doNotAlphabetize: true,
              columnHeader: "Appears",
              readOnly: !+this.props.duration
            }) }
            { Admin.renderField.bind(this)({ columnWidth: 3, entity: "webinarOffer", property: "startTime", columnHeader: (this.state["webinarOffer"].anchorPoint === "start" ? "Minutes In" : "Minutes Left") }) }
            { Admin.renderField.bind(this)({ columnWidth: 3, entity: "webinarOffer", property: "duration", columnHeader: "Duration (in seconds)" }) }
          </div>,
          <div key="3" className="row">
            { Admin.renderDropDown.bind(this)({
              columnWidth: 4,
              entity: "webinarOffer",
              property: "ctaButtonType",
              columnHeader: "CTA Type",
              optionLabel: "text",
              optionValue: "value"
            }) }
            { Admin.renderField.bind(this)({ columnWidth: 4, entity: "webinarOffer", property: "ctaButtonText", columnHeader: "CTA Text" }) }
            { Admin.renderField.bind(this)({ columnWidth: 4, entity: "webinarOffer", property: "ctaUrl", columnHeader: "CTA Url" }) }
          </div>
        ]);
      default:
        return null;
    }
  }

  componentDidUpdate() {
    Admin.resetNiceSelect({
      selector: '#new-entity select',
      func: Admin.changeField.bind(this, this.changeFieldArgs())
    });
  }
}

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

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ fetchDataForNew, createEntity }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(NewEntity);
