// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { Button, Form } from 'react-bootstrap';
import app from '../../../../app';
import FauxtonAPI from '../../../../core/api';
import ReactComponents from '../../../components/react-components';
import DesignDocSelector from './DesignDocSelector';
import ReduceEditor from './ReduceEditor';

const getDocUrl = app.helpers.getDocUrl;
const {CodeEditorPanel, ConfirmButton, LoadLines} = ReactComponents;

export default class IndexEditor extends Component {

  constructor(props) {
    super(props);
    this.saveView = this.saveView.bind(this);
    this.viewChange = this.viewChange.bind(this);
    this.updateMapCode = this.updateMapCode.bind(this);
  }

  // the code editor is a standalone component, so if the user goes from one edit view page to another, we need to
  // force an update of the editor panel
  componentDidUpdate(prevProps) {
    if (this.props.map !== prevProps.map && this.mapEditor) {
      this.mapEditor.update();
    }
  }

  isPartitionedView() {
    if (this.props.designDocId === 'new-doc') {
      return this.props.newDesignDocPartitioned;
    }
    return this.props.designDocPartitioned;
  }

  isCustomReduceSupported() {
    if (this.props.isDbPartitioned && this.props.reduce && !this.props.reduce.startsWith('_')) {
      const isDDocPartitioned = this.props.designDocId === 'new-doc' ? this.props.newDesignDocPartitioned : this.props.designDocPartitioned;
      return isDDocPartitioned ? false : true;
    }
    return true;
  }

  saveView(el) {
    el.preventDefault();

    if (!this.designDocSelector.validate()) {
      return;
    }

    if (!this.isCustomReduceSupported()) {
      FauxtonAPI.addNotification({
        msg: 'Partitioned views do not support custom reduce functions.',
        type: 'error',
        clear: true
      });
      return;
    }

    const encodedPartKey = this.isPartitionedView() && this.props.partitionKey ? encodeURIComponent(this.props.partitionKey) : '';
    const url = FauxtonAPI.urls('view', 'showView', this.props.database.safeID(), encodedPartKey,
      this.props.saveDesignDoc.safeID(), encodeURIComponent(this.props.viewName));
    this.props.saveView({
      database: this.props.database,
      isNewView: this.props.isNewView,
      viewName: this.props.viewName,
      designDoc: this.props.saveDesignDoc,
      designDocId: this.props.designDocId,
      isNewDesignDoc: this.props.isNewDesignDoc,
      originalViewName: this.props.originalViewName,
      originalDesignDocName: this.props.originalDesignDocName,
      map: this.mapEditor.getValue(),
      reduce: this.reduceEditor.getReduceValue(),
      designDocs: this.props.designDocs
    }, url);
  }

  viewChange(el) {
    this.props.changeViewName(el.target.value);
  }

  updateMapCode(code) {
    this.props.updateMapCode(code);
  }

  getCancelLink() {
    const encodedDatabase = encodeURIComponent(this.props.database.id);
    const encodedPartitionKey = this.props.partitionKey ? encodeURIComponent(this.props.partitionKey) : '';
    if (this.props.designDocId === 'new-doc' || this.props.isNewView) {
      return '#' + FauxtonAPI.urls('allDocs', 'app', encodedDatabase, encodedPartitionKey);
    }
    const encodedDDoc = app.utils.getSafeIdForDoc(this.props.designDocId);
    const encodedView = encodeURIComponent(this.props.viewName);
    return '#' + FauxtonAPI.urls('view', 'showView', encodedDatabase, encodedPartitionKey, encodedDDoc, encodedView);
  }

  render() {
    if (this.props.isLoading) {
      return (
        <div className="define-view">
          <LoadLines />
        </div>
      );
    }

    const pageHeader = (this.props.isNewView) ? 'New View' : 'Edit View';
    const btnLabel = (this.props.isNewView) ? 'Create Document and then Build Index' : 'Save Document and then Build Index';
    return (
      <div className="define-view" >
        <form className="form-horizontal view-query-save" onSubmit={this.saveView}>
          <h3 className="simple-header">{pageHeader}</h3>

          <div className="new-ddoc-section">
            <DesignDocSelector
              ref={(el) => { this.designDocSelector = el; }}
              designDocList={this.props.designDocList}
              isDbPartitioned={this.props.isDbPartitioned}
              selectedDesignDocName={this.props.designDocId}
              selectedDesignDocPartitioned={this.props.designDocPartitioned}
              newDesignDocName={this.props.newDesignDocName}
              newDesignDocPartitioned={this.props.newDesignDocPartitioned}
              onSelectDesignDoc={this.props.selectDesignDoc}
              onChangeNewDesignDocName={this.props.updateNewDesignDocName}
              onChangeNewDesignDocPartitioned={this.props.updateNewDesignDocPartitioned}
              docLink={getDocUrl('DESIGN_DOCS')} />
          </div>

          <div className="row">
            <div className="mb-3 col-12 col-lg-6 col-xxl-4">
              <label htmlFor="index-name">
                <span>Index name</span>
                <a
                  className="help-link"
                  data-bypass="true"
                  href={getDocUrl('VIEW_FUNCS')}
                  target="_blank"
                  rel="noopener noreferrer">
                  <i className="fonticon-help-circled"></i>
                </a>
              </label>
              <Form.Control type="text"
                id="index-name"
                value={this.props.viewName}
                onChange={this.viewChange}
                placeholder="Index name" />
            </div>
          </div>

          <div className="mb-3">
            <CodeEditorPanel
              id={'map-function'}
              ref={(el) => { this.mapEditor = el; }}
              title={"Map function"}
              docLink={getDocUrl('MAP_FUNCS')}
              blur={this.updateMapCode}
              allowZenMode={false}
              defaultCode={this.props.map} />
          </div>

          <ReduceEditor
            ref={(el) => { this.reduceEditor = el; }}
            customReducerSupported={this.isCustomReduceSupported()}
            {...this.props} />
          <div className="row mt-3">
            <div className="col-12">
              <ConfirmButton id="save-view" text={btnLabel} />
              <Button href={this.getCancelLink()} variant="cf-cancel" className="index-cancel-link">Cancel</Button>
            </div>
          </div>
        </form>
      </div>
    );
  }
}

IndexEditor.propTypes = {
  isLoading:PropTypes.bool.isRequired,
  isNewView: PropTypes.bool.isRequired,
  database: PropTypes.object.isRequired,
  isDbPartitioned: PropTypes.bool.isRequired,
  designDocId: PropTypes.string.isRequired,
  newDesignDocName: PropTypes.string.isRequired,
  viewName: PropTypes.string.isRequired,
  isNewDesignDoc: PropTypes.bool.isRequired,
  originalViewName: PropTypes.string,
  originalDesignDocName: PropTypes.string,
  designDocs: PropTypes.object,
  saveDesignDoc: PropTypes.object,
  partitionKey: PropTypes.string,
  updateNewDesignDocName: PropTypes.func.isRequired,
  changeViewName: PropTypes.func.isRequired,
  updateMapCode: PropTypes.func.isRequired
};
