/** @jsx h */
import { h, Component } from 'preact';

import { BASE_URL, API_BASE, DEFAULT_MAX_COMMENT_SIZE } from 'common/constants';
import { siteId, url, pageTitle } from 'common/settings';

import api from 'common/api';
import store from 'common/store';
import TextareaAutosize from 'components/input/textarea-autosize';

const RSS_THREAD_URL = `${BASE_URL}${API_BASE}/rss/post?site=${siteId}&url=${url}`;
const RSS_SITE_URL = `${BASE_URL}${API_BASE}/rss/site?site=${siteId}`;
const RSS_REPLIES_URL = `${BASE_URL}${API_BASE}/rss/reply?site=${siteId}&user=`;

export default class Input extends Component {
  constructor(props) {
    super(props);

    const config = store.get('config') || {};

    this.state = {
      preview: null,
      isErrorShown: false,
      errorMessage: null,
      isDisabled: false,
      maxLength: config.max_comment_size || DEFAULT_MAX_COMMENT_SIZE,
      text: props.value || '',
    };

    this.send = this.send.bind(this);
    this.getPreview = this.getPreview.bind(this);
    this.onInput = this.onInput.bind(this);
    this.onKeyDown = this.onKeyDown.bind(this);
  }

  componentDidMount() {
    store.onUpdate('config', config => {
      this.setState({ maxLength: (config && config.max_comment_size) || DEFAULT_MAX_COMMENT_SIZE });
    });
  }

  shouldComponentUpdate(nextProps, nextState) {
    return (
      nextProps.id !== this.props.id ||
      nextProps.mods !== this.props.mods ||
      nextProps.pid !== this.props.pid ||
      nextProps.value !== this.props.value ||
      nextProps.errorMessage !== this.props.errorMessage ||
      nextState !== this.state
    );
  }

  onKeyDown(e) {
    // send on cmd+enter / ctrl+enter
    if (e.keyCode === 13 && (e.metaKey || e.ctrlKey)) {
      this.send();
    }
  }

  onInput(e) {
    this.setState({
      preview: null,
      isErrorShown: false,
      errorMessage: null,
      text: e.target.value,
    });
  }

  send(e) {
    const text = this.state.text;
    const { mods = {}, pid, id } = this.props;

    if (e) e.preventDefault();

    if (!text || !text.trim()) return;

    if (text === this.props.value) {
      this.props.onCancel && this.props.onCancel();
      this.setState({ preview: null, text: '' });
    }

    this.setState({ isDisabled: true, isErrorShown: false });

    const request =
      mods.mode === 'edit'
        ? api.updateComment({ text, id })
        : api.addComment({ title: pageTitle || document.title, text, ...(pid ? { pid } : {}) });

    request
      .then(comment => {
        this.props.onSubmit && this.props.onSubmit(comment);
        this.setState({ preview: null, text: '' });
      })
      .catch(e => {
        if (
          e.response &&
          e.response.data &&
          typeof e.response.data.error === 'string' &&
          e.response.data.error.indexOf("parent comment with reply can't be edited") === 0
        ) {
          this.setState({ isErrorShown: true, errorMessage: 'Comment has reply, editing is not possible' });
          return;
        }
        this.setState({ isErrorShown: true, errorMessage: null });
      })
      .finally(() => this.setState({ isDisabled: false }));
  }

  getPreview() {
    const text = this.state.text;

    if (!text || !text.trim()) return;

    this.setState({ isErrorShown: false, errorMessage: null });

    api
      .getPreview({ text })
      .then(preview => this.setState({ preview }))
      .catch(() => {
        this.setState({ isErrorShown: true, errorMessage: null });
      });
  }

  render(props, { isDisabled, isErrorShown, errorMessage, preview, maxLength, text }) {
    const charactersLeft = maxLength - text.length;
    const { mods = {}, userId } = props;
    errorMessage = props.errorMessage || errorMessage;

    return (
      <form className={b('input', props)} onSubmit={this.send} aria-label="New comment">
        <div className="input__field-wrapper">
          <TextareaAutosize
            className="input__field"
            placeholder="Your comment here"
            value={text}
            maxLength={maxLength}
            onInput={this.onInput}
            onKeyDown={this.onKeyDown}
            disabled={isDisabled}
          />

          {charactersLeft < 100 && <span className="input__counter">{charactersLeft}</span>}
        </div>

        {(isErrorShown || !!errorMessage) && (
          <p className="input__error" role="alert">
            {errorMessage || 'Something went wrong. Please try again a bit later.'}
          </p>
        )}

        <div className="input__actions">
          <button
            className={b('input__button', {}, { type: 'preview' })}
            type="button"
            disabled={isDisabled}
            onClick={this.getPreview}
          >
            Preview
          </button>

          <button className={b('input__button', {}, { type: 'send' })} type="submit" disabled={isDisabled}>
            Send
          </button>

          {mods.type === 'main' && (
            <div className="input__rss">
              <div class="input__markdown">
                Styling with{' '}
                <a className="input__markdown-link" target="_blank" href="markdown-help.html" target="_blank">
                  Markdown
                </a>{' '}
                is supported
              </div>
              Subscribe to&nbsp;the{' '}
              <a className="input__rss-link" href={RSS_THREAD_URL} target="_blank">
                Thread
              </a>
              {', '}
              <a className="input__rss-link" href={RSS_SITE_URL} target="_blank">
                Site
              </a>{' '}
              or&nbsp;
              <a className="input__rss-link" href={RSS_REPLIES_URL + userId} target="_blank">
                Replies
              </a>{' '}
              by&nbsp;RSS
            </div>
          )}
        </div>

        {// TODO: it can be more elegant;
        // for example it can render full comment component here (or above textarea on mobile)
        !!preview && (
          <div className="input__preview-wrapper">
            <div
              className={b('input__preview', { mix: b('raw-content', {}, { theme: mods.theme }) })}
              dangerouslySetInnerHTML={{ __html: preview }}
            />
          </div>
        )}
      </form>
    );
  }
}
