'use strict';

var React = require('react');

var utils = require('../utils');
var i18n = require('../i18n');
var hub = require('../hub');
var {AttachmentsChangedEvent} = require('../events');
var RecordComponent = require('./RecordComponent');
var Link = require('../components/Link');


function getBrowseButtonTitle() {
  var platform = utils.getPlatform();
  if (platform === 'mac') {
    return i18n.trans('BROWSE_FS_MAC');
  } else if (platform === 'windows') {
    return i18n.trans('BROWSE_FS_WINDOWS');
  } else {
    return i18n.trans('BROWSE_FS');
  }
}


const CHILDREN_PER_PAGE = 15;


class ChildPosCache {

  constructor() {
    this.memo = [];
  }

  rememberPosition(record, page) {
    for (let i = 0; i < this.memo.length; i++) {
      if (this.memo[i][0] === record) {
        this.memo[i][1] = page;
        return;
      }
    }
    this.memo.unshift([record, page]);
    if (this.memo.length > 5) {
      this.memo.length = 5;
    }
  }

  getPosition(record, childCount) {
    for (let i = 0; i < this.memo.length; i++) {
      if (this.memo[i][0] === record) {
        let rv = this.memo[i][1];
        if (childCount !== undefined) {
          rv = Math.min(rv, Math.ceil(childCount / CHILDREN_PER_PAGE));
        }
        return rv;
      }
    }
    return 1;
  }
}


class Sidebar extends RecordComponent {

  constructor(props) {
    super(props);

    this.state = this._getInitialState();
    this.childPosCache = new ChildPosCache();
    this.onAttachmentsChanged = this.onAttachmentsChanged.bind(this);
  }

  _getInitialState() {
    return {
      recordAttachments: [],
      recordChildren: [],
      recordAlts: [],
      canHaveAttachments: false,
      canHaveChildren: false,
      isAttachment: false,
      canBeDeleted: false,
      recordExists: false,
      lastRecordRequest: null,
      childrenPage: 1
    };
  }

  componentDidMount() {
    super.componentDidMount();
    this._updateRecordInfo();

    hub.subscribe(AttachmentsChangedEvent, this.onAttachmentsChanged);
  }

  componentDidUpdate(prevProps, prevState) {
    super.componentDidUpdate(prevProps, prevState);
    if (prevProps.params.path !== this.props.params.path) {
      this._updateRecordInfo();
    }
  }

  componentWillUnmount() {
    super.componentWillUnmount();
    hub.unsubscribe(AttachmentsChangedEvent, this.onAttachmentsChanged);
  }

  onAttachmentsChanged(event) {
    if (event.recordPath === this.getRecordPath()) {
      this._updateRecordInfo();
    }
  }

  _updateRecordInfo() {
    var path = this.getRecordPath();
    if (path === null) {
      this.setState(this._getInitialState());
      return;
    }

    this.setState({
      lastRecordRequest: path,
    }, () => {
      utils.loadData('/recordinfo', {path: path})
        .then((resp) => {
          // we're already fetching something else.
          if (path !== this.state.lastRecordRequest) {
            return;
          }
          var alts = resp.alts;
          alts.sort((a, b) => {
            var nameA = (a.is_primary ? 'A' : 'B') + i18n.trans(a.name_i18n);
            var nameB = (b.is_primary ? 'A' : 'B') + i18n.trans(b.name_i18n);
            return nameA === nameB ? 0 : nameA < nameB ? -1 : 1;
          });
          this.setState({
            recordAttachments: resp.attachments,
            recordChildren: resp.children,
            recordAlts: alts,
            canHaveAttachments: resp.can_have_attachments,
            canHaveChildren: resp.can_have_children,
            isAttachment: resp.is_attachment,
            canBeDeleted: resp.can_be_deleted,
            recordExists: resp.exists,
            childrenPage: this.childPosCache.getPosition(
              path, resp.children.length),
          });
        });
    });
  }

  fsOpen(event) {
    event.preventDefault();
    utils.apiRequest('/browsefs', {data: {
      path: this.getRecordPath(),
      alt: this.getRecordAlt()
    }, method: 'POST'})
      .then((resp) => {
        if (!resp.okay) {
          alert(i18n.trans('ERROR_CANNOT_BROWSE_FS'));
        }
      });
  }

  renderPageActions() {
    var urlPath = this.getUrlRecordPathWithAlt();
    var links = [];
    var linkParams = {path: urlPath};
    var deleteLink = null;

    links.push(
      <li key='edit'>
        <Link to={`${urlPath}/edit`}>
          {this.state.isAttachment ?
           i18n.trans('EDIT_METADATA') :
           i18n.trans('EDIT')}
         </Link>
       </li>
    );

    if (this.state.canBeDeleted) {
      links.push(
        <li key='delete'><Link to={`${urlPath}/delete`}>
          {i18n.trans('DELETE')}</Link></li>
      );
    }

    links.push(
      <li key='preview'><Link to={`${urlPath}/preview`}>
        {i18n.trans('PREVIEW')}</Link></li>
    );

    if (this.state.recordExists) {
      links.push(
        <li key='fs-open'>
          <a href="#" onClick={this.fsOpen.bind(this)}>
            {getBrowseButtonTitle()}
          </a>
        </li>
      );
    }

    if (this.state.canHaveChildren) {
      links.push(
        <li key='add-child'><Link to={`${urlPath}/add-child`}>
          {i18n.trans('ADD_CHILD_PAGE')}</Link></li>
      );
    }

    if (this.state.canHaveAttachments) {
      links.push(
        <li key='add-attachment'><Link to={`${urlPath}/upload`}>
          {i18n.trans('ADD_ATTACHMENT')}</Link></li>
      );
    }

    var title = this.state.isAttachment
      ? i18n.trans('ATTACHMENT_ACTIONS')
      : i18n.trans('PAGE_ACTIONS');

    return (
      <div key="actions" className="section">
        <h3>{title}</h3>
        <ul className="nav">
          {links}
          {deleteLink}
        </ul>
      </div>
    );
  }

  renderAlts() {
    if (this.state.recordAlts.length < 2) {
      return null;
    }

    var alt = this.getRecordAlt();

    var items = this.state.recordAlts.map((item) => {
      var title = i18n.trans(item.name_i18n);
      var className = 'alt';
      if (item.is_primary) {
        title += ' (' + i18n.trans('PRIMARY_ALT') + ')';
      } else if (item.primary_overlay) {
        title += ' (' + i18n.trans('PRIMARY_OVERLAY') + ')';
      }
      if (!item.exists) {
        className += ' alt-missing';
      }

      var path = this.getPathToAdminPage(null, {
        path: this.getUrlRecordPathWithAlt(null, item.alt)
      });
      return (
        <li key={item.alt} className={className}>
          <Link to={path}>{title}</Link>
        </li>
      );
    });

    return (
      <div key="alts" className="section">
        <h3>{i18n.trans('ALTS')}</h3>
        <ul className="nav">
          {items}
        </ul>
      </div>
    );
  }

  renderChildPagination() {
    let pages = Math.ceil(this.state.recordChildren.length / CHILDREN_PER_PAGE);
    if (pages <= 1) {
      return null;
    }
    let page = this.state.childrenPage;
    let goToPage = (diff, event) => {
      event.preventDefault();
      let newPage = page +diff;
      this.childPosCache.rememberPosition(this.getRecordPath(), newPage);
      this.setState({
        childrenPage: newPage
      });
    };

    return (
      <li className="pagination">
        {page > 1
          ? <a href="#" onClick={goToPage.bind(this, -1)}>«</a>
          : <em>«</em>}
        <span className="page">{page + ' / ' + pages}</span>
        {page < pages
          ? <a href="#" onClick={goToPage.bind(this, +1)}>»</a>
          : <em>»</em>}
      </li>
    );
  }

  renderChildActions() {
    var target = this.isRecordPreviewActive() ? 'preview' : 'edit';

    var children = this.state.recordChildren.slice(
      (this.state.childrenPage - 1) * CHILDREN_PER_PAGE,
      this.state.childrenPage * CHILDREN_PER_PAGE);

    var items = children.map((child) => {
      var urlPath = this.getUrlRecordPathWithAlt(child.path);
      return (
        <li key={child.id}>
          <Link to={`${urlPath}/${target}`}>
            {i18n.trans(child.label_i18n)}</Link>
        </li>
      )
    });

    if (items.length == 0) {
      items.push(
        <li key="_missing">
          <em>{i18n.trans('NO_CHILD_PAGES')}</em>
        </li>
      );
    }

    return (
      <div key="children" className="section">
        <h3>{i18n.trans('CHILD_PAGES')}</h3>
        <ul className="nav record-children">
          {this.renderChildPagination()}
          {items}
        </ul>
      </div>
    );
  }

  renderAttachmentActions() {
    var items = this.state.recordAttachments.map((atch) => {
      var urlPath = this.getUrlRecordPathWithAlt(atch.path);
      return (
        <li key={atch.id}>
          <Link to={`${urlPath}/edit`}>
            {atch.id} ({atch.type})</Link>
        </li>
      )
    });

    if (items.length == 0) {
      items.push(
        <li key="_missing">
          <em>{i18n.trans('NO_ATTACHMENTS')}</em>
        </li>
      );
    }

    return (
      <div key="attachments" className="section">
        <h3>{i18n.trans('ATTACHMENTS')}</h3>
        <ul className="nav record-attachments">
          {items}
        </ul>
      </div>
    );
  }

  render() {
    var sections = [];

    if (this.getRecordPath() !== null) {
      sections.push(this.renderPageActions());
    }

    sections.push(this.renderAlts());

    if (this.state.canHaveChildren) {
      sections.push(this.renderChildActions());
    }

    if (this.state.canHaveAttachments) {
      sections.push(this.renderAttachmentActions());
    }

    return <div className="sidebar-wrapper">{sections}</div>;
  }
}

module.exports = Sidebar;
