// 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 FauxtonAPI from '../../../core/api';
import app from '../../../app';
import React from 'react';
import Constants from '../constants';
import Components from '../../components/react-components';

const { StyledSelect } = Components;

export class ReplicationAuth extends React.Component {

  constructor (props) {
    super(props);
    this.onChangeType = this.onChangeType.bind(this);
    this.onChangeValue = this.onChangeValue.bind(this);

    // init auth extensions
    // The extension should provide:
    //   - 'inputComponent' a React component that will be displayed when the user selects the auth method.
    //   - 'typeValue' field with an arbitrary ID representing the auth type the extension supports.
    //   - 'typeLabel' field containing the display label for the authentication method.
    this.customAuths = FauxtonAPI.getExtensions('Replication:Auth');
    if (!this.customAuths) {
      this.customAuths = [];
    }
    this.customAuthTypes = this.customAuths.map(auth => auth.typeValue);
  }

  getAuthOptions = () => {
    const userPasswordLabel = app.i18n.en_US['replication-user-password-auth-label'];
    const authOptions = [
      { value: Constants.REPLICATION_AUTH_METHOD.NO_AUTH, label: 'None' },
      { value: Constants.REPLICATION_AUTH_METHOD.BASIC, label: userPasswordLabel }
    ];
    this.customAuths.map(auth => {
      authOptions.push({ value: auth.typeValue, label: auth.typeLabel });
    });

    return authOptions.map(option => <option value={option.value} key={option.value}>{option.label}</option>);
  }

  onChangeType(newType) {
    this.props.onChangeAuthType(newType);
  }

  onChangeValue(newValue) {
    this.props.onChangeAuth(newValue);
  }

  getAuthInputFields(authValue, authType) {
    const {authId} = this.props;
    if (authType == Constants.REPLICATION_AUTH_METHOD.BASIC) {
      return <UserPasswordAuthInput onChange={this.onChangeValue} auth={authValue} authId={authId}/>;
    }
    const matchedAuths = this.customAuths.filter(el => el.typeValue === authType);
    if (matchedAuths && matchedAuths.length > 0) {
      const InputComp = matchedAuths[0].inputComponent;
      return <InputComp onChange={this.onChangeValue} auth={authValue} />;
    }

    return null;
  }

  render () {
    const {credentials, authType, authId} = this.props;
    return (<React.Fragment>
      <div className="replication__section">
        <div className="replication__input-label">
          Authentication:
        </div>
        <div className="replication__input-select">
          <StyledSelect
            selectContent={this.getAuthOptions()}
            selectChange={(e) => this.onChangeType(e.target.value)}
            selectId={'select-' + authId}
            selectValue={authType} />
        </div>
      </div>
      {this.getAuthInputFields(credentials, authType)}
    </React.Fragment>);
  }
}

ReplicationAuth.propTypes = {
  authId: PropTypes.string.isRequired,
  authType: PropTypes.string.isRequired,
  credentials: PropTypes.object,
  onChangeAuth: PropTypes.func.isRequired,
  onChangeAuthType: PropTypes.func.isRequired
};

ReplicationAuth.defaultProps = {
  authType: Constants.REPLICATION_AUTH_METHOD.NO_AUTH,
  onChangeAuthType: () => {},
  onChangeAuth: () => {}
};

export class UserPasswordAuthInput extends React.Component {

  constructor (props) {
    super(props);
    this.updatePassword = this.updatePassword.bind(this);
    this.updateUsername = this.updateUsername.bind(this);
    this.state = {
      username: props.auth && props.auth.username ? props.auth.username : '',
      password: props.auth && props.auth.password ? props.auth.password : ''
    };
  }

  updatePassword(newValue) {
    this.setState({password: newValue});
    this.props.onChange({
      username: this.state.username,
      password: newValue
    });
  }

  updateUsername(newValue) {
    this.setState({username: newValue});
    this.props.onChange({
      username: newValue,
      password: this.state.password
    });
  }

  render () {
    const usernamePlaceholder = app.i18n.en_US['replication-username-input-placeholder'];
    const passwordPlaceholder = app.i18n.en_US['replication-password-input-placeholder'];
    const { authId } = this.props;
    return (
      <React.Fragment>
        <div className="replication__section">
          <div className="replication__input-label"></div>
          <div>
            <input
              id={authId + '-username'}
              type="text"
              placeholder={usernamePlaceholder}
              value={this.state.username}
              onChange={(e) => this.updateUsername(e.target.value)}
              readOnly={this.props.usernameReadOnly}
            />
          </div>
        </div>
        <div className="replication__section">
          <div className="replication__input-label"></div>
          <div>
            <input
              id={authId + '-password'}
              type="password"
              placeholder={passwordPlaceholder}
              value={this.state.password}
              onChange={(e) => this.updatePassword(e.target.value)}
            />
          </div>
        </div>
      </React.Fragment>
    );
  }
}

UserPasswordAuthInput.propTypes = {
  auth: PropTypes.object.isRequired,
  onChange: PropTypes.func.isRequired
};
