// 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.

define([
  "app",
  "api",
  "react",
  "addons/cors/stores",
  "addons/cors/resources",
  "addons/cors/actions",
  'addons/components/react-components.react'

], function (app, FauxtonAPI, React, Stores, Resources, Actions, ReactComponents) {
  var corsStore = Stores.corsStore;

  var validateOrigin = function (origin) {
    if (!Resources.validateCORSDomain(origin)) {
      FauxtonAPI.addNotification({
        msg: 'Please enter a valid domain, starting with http/https.',
        type: 'error',
        clear: true
      });

      return false;
    }

    return true;
  };

  var OriginRow = React.createClass({

    getInitialState: function () {
      return {
        edit: false,
        updatedOrigin: this.props.origin
      };
    },

    editOrigin: function (event) {
      event.preventDefault();
      this.setState({edit: !this.state.edit});
    },

    updateOrigin: function (event) {
      event.preventDefault();
      if (!validateOrigin(this.state.updatedOrigin)) {
        return;
      }
      this.props.updateOrigin(this.state.updatedOrigin, this.props.origin);
      this.setState({edit: false});
    },

    deleteOrigin: function (event) {
      event.preventDefault();
      if (!window.confirm('Are you sure you want to delete ' + this.props.origin)) {
        return;
      }

      this.props.deleteOrigin(this.props.origin);
    },

    onInputChange: function (event) {
      this.setState({updatedOrigin: event.target.value});
    },

    onKeyUp: function (e) {
      if (e.keyCode === 13) {   //enter key
        return this.updateOrigin(e);
      }
    },

    createOriginDisplay: function () {
      if (this.state.edit) {
        return (
          <div className="input-append edit-domain-section">
            <input type="text" name="update_origin_domain" onChange={this.onInputChange}  onKeyUp={this.onKeyUp} value={this.state.updatedOrigin} />
            <button onClick={this.updateOrigin} className="btn btn-primary update-origin"> Update </button>
          </div>
        );
      }

      return <div className="js-url url-display">{this.props.origin}</div>;
    },

    render: function () {
      var display = this.createOriginDisplay();
      return (
        <tr>
          <td>
            { display }
          </td>
          <td width="30">
            <span className="fonticon-pencil" onClick={this.editOrigin} title="Click to edit"></span>
          </td>
          <td width="30">
            <span className="fonticon-trash" onClick={this.deleteOrigin} title="Click to delete"></span>
          </td>
        </tr>
      );
    }

  });

  var OriginTable = React.createClass({

    createRows: function () {
      return _.map(this.props.origins, function (origin, i) {
        return <OriginRow
          updateOrigin={this.props.updateOrigin}
          deleteOrigin={this.props.deleteOrigin}
          key={i} origin={origin} />;
      }, this);
    },

    render: function () {
      if (!this.props.origins) {
        return null;
      }

      if (!this.props.isVisible || this.props.origins.length === 0) {
        return null;
      }

      var origins = this.createRows();

      return (
        <table id="origin-domain-table" className="table table-striped">
          <tbody>
            {origins}
          </tbody>
        </table>
      );
    }

  });

  var OriginInput = React.createClass({
    getInitialState: function () {
      return {
        origin: ''
      };
    },

    onInputChange: function (e) {
      this.setState({origin: e.target.value});
    },

    addOrigin: function (event) {
      event.preventDefault();
      if (!validateOrigin(this.state.origin)) {
        return;
      }

      var url = Resources.normalizeUrls(this.state.origin);

      this.props.addOrigin(url);
      this.setState({origin: ''});
    },

    onKeyUp: function (e) {
      if (e.keyCode == 13) {   //enter key
        return this.addOrigin(e);
      }
    },

    render: function () {
      if (!this.props.isVisible) {
        return null;
      }

      return (
        <div id="origin-domains-container">
          <div className="origin-domains">
            <div className="input-append">
              <input type="text" name="new_origin_domain" onChange={this.onInputChange} onKeyUp={this.onKeyUp} value={this.state.origin} placeholder="e.g., https://site.com"/>
              <button onClick={this.addOrigin} className="btn btn-primary add-domain"> Add </button>
            </div>
          </div>
        </div>
      );
    }

  });

  var Origins = React.createClass({

    onOriginChange: function (event) {
      if (event.target.value === 'all' && this.props.isAllOrigins) {
        return;   // do nothing if all origins is already selected
      }
      if (event.target.value === 'selected' && !this.props.isAllOrigins) {
        return;   // do nothing if specific origins is already selected
      }

      this.props.originChange(event.target.value === 'all');
    },

    render: function () {

      if (!this.props.corsEnabled) {
        return null;
      }

      return (
        <div>
          <p><strong> Origin Domains </strong> </p>
          <p>Databases will accept requests from these domains: </p>
          <label className="radio">
            <input type="radio" checked={this.props.isAllOrigins} value="all" onChange={this.onOriginChange} name="all-domains"/> All domains ( * )
          </label>
          <label className="radio">
            <input type="radio" checked={!this.props.isAllOrigins} value="selected" onChange={this.onOriginChange} name="selected-domains"/> Restrict to specific domains
          </label>
        </div>
      );
    }
  });

  var CORSController = React.createClass({

    getStoreState: function () {
      return {
        corsEnabled: corsStore.isEnabled(),
        origins: corsStore.getOrigins(),
        isAllOrigins: corsStore.isAllOrigins(),
        configChanged: corsStore.hasConfigChanged(),
        shouldSaveChange: corsStore.shouldSaveChange(),
        node: corsStore.getNode(),
        isLoading: corsStore.getIsLoading()
      };
    },

    getInitialState: function () {
      return this.getStoreState();
    },

    componentDidMount: function () {
      corsStore.on('change', this.onChange, this);
    },

    componentWillUnmount: function () {
      corsStore.off('change', this.onChange);
    },

    componentDidUpdate: function () {
      if (this.state.shouldSaveChange) {
        this.save();
      }
    },

    onChange: function () {
      this.setState(this.getStoreState());
    },

    enableCorsChange: function () {
      if (this.state.corsEnabled && !_.isEmpty(this.state.origins) ) {
        var result = window.confirm(app.i18n.en_US['cors-disable-cors-prompt']);
        if (!result) { return; }
      }

      Actions.toggleEnableCors();
    },

    save: function () {
      Actions.saveCors({
        enableCors: this.state.corsEnabled,
        origins: this.state.origins,
        node: this.state.node
      });
    },

    deleteOrigin: function (origin) {
      Actions.deleteOrigin(origin);
    },

    originChange: function (isAllOrigins) {
      if (isAllOrigins && !_.isEmpty(this.state.origins)) {
        var result = window.confirm('Are you sure? Switching to all origin domains will overwrite your specific origin domains.');
        if (!result) { return; }
      }

      Actions.originChange(isAllOrigins);
    },

    addOrigin: function (origin) {
      Actions.addOrigin(origin);
    },

    updateOrigin: function (updatedOrigin, originalOrigin) {
      Actions.updateOrigin(updatedOrigin, originalOrigin);
    },

    methodChange: function (httpMethod) {
      Actions.methodChange(httpMethod);
    },

    render: function () {
      var isVisible = _.all([this.state.corsEnabled, !this.state.isAllOrigins]);

      var originSettings = (
        <div id={this.state.corsEnabled ? 'collapsing-container' : ''}>
          <Origins corsEnabled={this.state.corsEnabled} originChange={this.originChange} isAllOrigins={this.state.isAllOrigins}/>
          <OriginTable updateOrigin={this.updateOrigin} deleteOrigin={this.deleteOrigin} isVisible={isVisible} origins={this.state.origins} />
          <OriginInput addOrigin={this.addOrigin} isVisible={isVisible} />
        </div>
      );

      if (this.state.isLoading) {
        originSettings = (<ReactComponents.LoadLines />);
      }

      return (
        <div className="cors-page">
          <header id="cors-header">
            <p>{app.i18n.en_US['cors-notice']}</p>
          </header>

          <form id="corsForm" onSubmit={this.save}>
            <div className="cors-enable">
              {this.state.corsEnabled ? 'Cors is currently enabled.' : 'Cors is currently disabled.'}
              <br />
              <button
                type="button"
                className="enable-disable btn btn-small btn-success"
                onClick={this.enableCorsChange}
                disabled={this.state.isLoading ? 'disabled' : null}
              >
                {this.state.corsEnabled ? 'Disable CORS' : 'Enable CORS'}
              </button>
            </div>
            {originSettings}
          </form>
        </div>
      );
    }
  });

  return {
    CORSController: CORSController,
    OriginInput: OriginInput,
    Origins: Origins,
    OriginTable: OriginTable,
    OriginRow: OriginRow
  };
});
