import * as _ from 'lodash-es';
import * as React from 'react';

import { k8sPatch, referenceForModel } from '../../module/k8s';
import { createModalLauncher, ModalTitle, ModalBody, ModalSubmitFooter } from '../factory/modal';
import { PromiseComponent, ResourceIcon, SelectorInput } from '../utils';

const LABELS_PATH = '/metadata/labels';
const TEMPLATE_SELECTOR_PATH = '/spec/template/metadata/labels';

class BaseLabelsModal extends PromiseComponent {
  constructor(props) {
    super(props);
    this._submit = this._submit.bind(this);
    this._cancel = props.cancel.bind(this);
    const labels = SelectorInput.arrayify(_.get(props.resource, props.path.split('/').slice(1)));
    this.state = Object.assign(this.state, {
      labels,
    });
    this.createPath = !labels.length;
  }

  _submit(e) {
    e.preventDefault();

    const { kind, path, resource, isPodSelector } = this.props;

    const patch = [
      {
        op: this.createPath ? 'add' : 'replace',
        path,
        value: SelectorInput.objectify(this.state.labels),
      },
    ];

    // https://kubernetes.io/docs/user-guide/deployments/#selector
    //   .spec.selector must match .spec.template.metadata.labels, or it will be rejected by the API
    const updateTemplate =
      isPodSelector && !_.isEmpty(_.get(resource, TEMPLATE_SELECTOR_PATH.split('/').slice(1)));

    if (updateTemplate) {
      patch.push({
        path: TEMPLATE_SELECTOR_PATH,
        op: 'replace',
        value: SelectorInput.objectify(this.state.labels),
      });
    }
    const promise = k8sPatch(kind, resource, patch);
    this.handlePromise(promise).then(this.props.close);
  }

  render() {
    const { kind, resource, description, message, labelClassName } = this.props;

    return (
      <form onSubmit={this._submit} name="form" className="modal-content">
        <ModalTitle>Edit {description || 'Labels'}</ModalTitle>
        <ModalBody>
          <div className="row co-m-form-row">
            <div className="col-sm-12">
              {message ||
                'Labels help you organize and select resources. Adding labels below will let you query for objects that have similar, overlapping or dissimilar labels.'}
            </div>
          </div>
          <div className="row co-m-form-row">
            <div className="col-sm-12">
              <label htmlFor="tags-input" className="control-label">
                {_.capitalize(description) || 'Labels'} for{' '}
                <ResourceIcon kind={kind.crd ? referenceForModel(kind) : kind.kind} />{' '}
                {resource.metadata.name}
              </label>
              <SelectorInput
                onChange={(labels) => this.setState({ labels })}
                tags={this.state.labels}
                labelClassName={labelClassName || `co-text-${kind.id}`}
                autoFocus
              />
            </div>
          </div>
        </ModalBody>
        <ModalSubmitFooter
          errorMessage={this.state.errorMessage}
          inProgress={this.state.inProgress}
          submitText="Save"
          cancel={this._cancel}
        />
      </form>
    );
  }
}

export const labelsModal = createModalLauncher((props) => (
  <BaseLabelsModal path={LABELS_PATH} {...props} />
));

export const podSelectorModal = createModalLauncher((props) => (
  <BaseLabelsModal
    path={
      ['replicationcontrolleres', 'services'].includes(props.kind.plural)
        ? '/spec/selector'
        : '/spec/selector/matchLabels'
    }
    isPodSelector={true}
    description="Pod Selector"
    message={`Determines the set of pods targeted by this ${props.kind.label.toLowerCase()}.`}
    labelClassName="co-text-pod"
    {...props}
  />
));
