import React from 'react';
import lbry from '../lbry.js';
import {Link} from '../component/link.js';
import {Icon} from '../component/common.js';
import Modal from './modal.js';
import FormField from './form.js';
import {ToolTip} from '../component/tooltip.js';
import {DropDownMenu, DropDownMenuItem} from './menu.js';

let WatchLink = React.createClass({
  propTypes: {
    streamName: React.PropTypes.string,
  },
  handleClick: function() {
    this.setState({
      loading: true,
    })
    lbry.getCostInfoForName(this.props.streamName, ({cost}) => {
      lbry.getBalance((balance) => {
        if (cost > balance) {
          this.setState({
            modal: 'notEnoughCredits',
            loading: false,
          });
        } else {
          window.location = '?watch=' + this.props.streamName;
        }
      });
    });
  },
  getInitialState: function() {
    return {
      modal: null,
      loading: false,
    };
  },
  closeModal: function() {
    this.setState({
      modal: null,
    });
  },
  render: function() {
    return (
      <div className="button-container">
        <Link button="primary" disabled={this.state.loading} label="Watch" icon="icon-play" onClick={this.handleClick} />
        <Modal contentLabel="Not enough credits" isOpen={this.state.modal == 'notEnoughCredits'} onConfirmed={this.closeModal}>
          You don't have enough LBRY credits to pay for this stream.
        </Modal>
      </div>
    );
  }
});

let FileActionsRow = React.createClass({
  _isMounted: false,
  _fileInfoSubscribeId: null,

  propTypes: {
    streamName: React.PropTypes.string,
    sdHash: React.PropTypes.string.isRequired,
    metadata: React.PropTypes.object
  },
  getInitialState: function() {
    return {
      fileInfo: null,
      modal: null,
      menuOpen: false,
      deleteChecked: false,
      attemptingDownload: false,
      attemptingRemove: false
    }
  },
  onFileInfoUpdate: function(fileInfo) {
    if (this._isMounted) {
      this.setState({
        fileInfo: fileInfo ? fileInfo : false,
        attemptingDownload: fileInfo ? false : this.state.attemptingDownload
      });
    }
  },
  tryDownload: function() {
    this.setState({
      attemptingDownload: true,
      attemptingRemove: false
    });
    lbry.getCostInfoForName(this.props.streamName, ({cost}) => {
      lbry.getBalance((balance) => {
        if (cost > balance) {
          this.setState({
            modal: 'notEnoughCredits',
            attemptingDownload: false,
          });
        } else {
          lbry.getStream(this.props.streamName, (streamInfo) => {
            if (streamInfo === null || typeof streamInfo !== 'object') {
              this.setState({
                modal: 'timedOut',
                attemptingDownload: false,
              });
            }
          });
        }
      });
    });
  },
  closeModal: function() {
    this.setState({
      modal: null,
    })
  },
  onDownloadClick: function() {
    if (!this.state.fileInfo && !this.state.attemptingDownload) {
      this.tryDownload();
    }
  },
  onOpenClick: function() {
    if (this.state.fileInfo && this.state.fileInfo.completed) {
      lbry.openFile(this.props.sdHash);
    }
  },
  handleDeleteCheckboxClicked: function(event) {
    this.setState({
      deleteChecked: event.target.checked,
    });
  },
  handleRevealClicked: function() {
    if (this.state.fileInfo && this.state.fileInfo.download_path) {
      lbry.revealFile(this.props.sdHash);
    }
  },
  handleRemoveClicked: function() {
    this.setState({
      modal: 'confirmRemove',
    });
  },
  handleRemoveConfirmed: function() {
    if (this.props.streamName) {
      lbry.removeFile(this.props.sdHash, this.props.streamName, this.state.deleteChecked);
    } else {
      alert('this file cannot be deleted because lbry is a retarded piece of shit');
    }
    this.setState({
      modal: null,
      fileInfo: false,
      attemptingDownload: false
    });
  },
  openMenu: function() {
    this.setState({
      menuOpen: !this.state.menuOpen,
    });
  },
  componentDidMount: function() {
    this._isMounted = true;
    this._fileInfoSubscribeId = lbry.fileInfoSubscribe(this.props.sdHash, this.onFileInfoUpdate);
  },
  componentWillUnmount: function() {
    this._isMounted = false;
    if (this._fileInfoSubscribeId) {
      lbry.fileInfoUnsubscribe(this.props.sdHash, this._fileInfoSubscribeId);
    }
  },
  render: function() {
    if (this.state.fileInfo === null)
    {
      return null;
    }

    const openInFolderMessage = window.navigator.platform.startsWith('Mac') ? 'Open in Finder' : 'Open in Folder',
      showMenu = !!this.state.fileInfo;

    let linkBlock;
    if (this.state.fileInfo === false && !this.state.attemptingDownload) {
      linkBlock = <Link button="text" label="Download" icon="icon-download" onClick={this.onDownloadClick} />;
    } else if (this.state.attemptingDownload || !this.state.fileInfo.completed) {
      const
        progress = this.state.fileInfo ? this.state.fileInfo.written_bytes / this.state.fileInfo.total_bytes * 100 : 0,
        label = this.state.fileInfo ? progress.toFixed(0) + '% complete' : 'Connecting...',
        labelWithIcon = <span className="button__content"><Icon icon="icon-download" /><span>{label}</span></span>;

      linkBlock = (
        <div className="faux-button-block file-actions__download-status-bar">
          <div className="faux-button-block file-actions__download-status-bar-overlay" style={{ width: progress + '%' }}>{labelWithIcon}</div>
          {labelWithIcon}
        </div>
      );
    } else {
      linkBlock = <Link label="Open" button="text" icon="icon-folder-open" onClick={this.onOpenClick} />;
    }

    return (
      <div>
        {(this.props.metadata.content_type && this.props.metadata.content_type.startsWith('video/')) ? <WatchLink streamName={this.props.streamName} /> : null}
        {this.state.fileInfo !== null || this.state.fileInfo.isMine ?
         <div className="button-container">{linkBlock}</div>
          : null}
        { showMenu ?
          <DropDownMenu>
            <DropDownMenuItem key={0} onClick={this.handleRevealClicked} label={openInFolderMessage} />
            <DropDownMenuItem key={1} onClick={this.handleRemoveClicked} label="Remove..." />
          </DropDownMenu> : '' }
        <Modal isOpen={this.state.modal == 'notEnoughCredits'} contentLabel="Not enough credits"
               onConfirmed={this.closeModal}>
          You don't have enough LBRY credits to pay for this stream.
        </Modal>
        <Modal isOpen={this.state.modal == 'timedOut'} contentLabel="Download failed"
               onConfirmed={this.closeModal}>
          LBRY was unable to download the stream <strong>lbry://{this.props.streamName}</strong>.
        </Modal>
        <Modal isOpen={this.state.modal == 'confirmRemove'} contentLabel="Not enough credits"
               type="confirm" confirmButtonLabel="Remove" onConfirmed={this.handleRemoveConfirmed}
               onAborted={this.closeModal}>
          <p>Are you sure you'd like to remove <cite>{this.props.metadata.title}</cite> from LBRY?</p>

          <label><FormField type="checkbox" checked={this.state.deleteChecked} onClick={this.handleDeleteCheckboxClicked} /> Delete this file from my computer</label>
        </Modal>
      </div>
    );
  }
});

export let FileActions = React.createClass({
  _isMounted: false,
  _fileInfoSubscribeId: null,

  propTypes: {
    streamName: React.PropTypes.string,
    sdHash: React.PropTypes.string.isRequired,
    metadata: React.PropTypes.object
  },
  getInitialState: function() {
    return {
      available: true,
      forceShowActions: false,
      fileInfo: null,
    }
  },
  onShowFileActionsRowClicked: function() {
    this.setState({
      forceShowActions: true,
    });
  },
  onFileInfoUpdate: function(fileInfo) {
    this.setState({
      fileInfo: fileInfo,
    });
  },
  componentDidMount: function() {
    this._isMounted = true;
    this._fileInfoSubscribeId = lbry.fileInfoSubscribe(this.props.sdHash, this.onFileInfoUpdate);
    lbry.getPeersForBlobHash(this.props.sdHash, (peers) => {
      if (!this._isMounted) {
        return;
      }

      this.setState({
        available: peers.length > 0,
      });
    });
  },
  componentWillUnmount: function() {
    this._isMounted = false;
  },
  render: function() {
    const fileInfo = this.state.fileInfo;
    if (fileInfo === null) {
      return null;
    }

    return (<section className="file-actions">
      {
        fileInfo || this.state.available || this.state.forceShowActions
          ? <FileActionsRow sdHash={this.props.sdHash} metadata={this.props.metadata} streamName={this.props.streamName} />
          : <div>
              <div className="button-container empty">This file is not currently available.</div>
              <div className="button-container">
                <ToolTip label="Why?"
                         body="The content on LBRY is hosted by its users. It appears there are no users connected that have this file at the moment." />
              </div>
              <div className="button-container">
                <Link label="Try Anyway" onClick={this.onShowFileActionsRowClicked} />
              </div>
            </div>
      }
    </section>);
  }
});