import React from 'react';
import lbry from '../lbry.js';
import {Link, WatchLink} from '../component/link.js';
import {Menu, MenuItem} from '../component/menu.js';
import Modal from '../component/modal.js';
import {BusyMessage, Thumbnail} from '../component/common.js';

var moreMenuStyle = {
  position: 'absolute',
  display: 'block',
  top: '26px',
  right: '13px',
};
var MyFilesRowMoreMenu = React.createClass({
  propTypes: {
    title: React.PropTypes.string.isRequired,
    path: React.PropTypes.string.isRequired,
    completed: React.PropTypes.bool.isRequired,
    lbryUri: React.PropTypes.string.isRequired,
  },
  handleRevealClicked: function() {
    lbry.revealFile(this.props.path);
  },
  handleRemoveClicked: function() {
    lbry.deleteFile(this.props.lbryUri, false);
  },
  handleDeleteClicked: function() {
    this.setState({
      modal: 'confirmDelete',
    });
  },
  handleDeleteConfirmed: function() {
    lbry.deleteFile(this.props.lbryUri);
    this.setState({
      modal: null,
    });
  },
  closeModal: function() {
    this.setState({
      modal: null,
    });
  },
  getInitialState: function() {
    return {
      modal: null,
    };
  },
  render: function() {
    return (
      <div style={moreMenuStyle}>
        <Menu {...this.props}>
          <section className="card">
            <MenuItem onClick={this.handleRevealClicked} label="Reveal file" /> {/* @TODO: Switch to OS specific wording */}
            <MenuItem onClick={this.handleRemoveClicked} label="Remove from LBRY" />
            <MenuItem onClick={this.handleDeleteClicked} label="Remove and delete file" />
          </section>
        </Menu>
        <Modal isOpen={this.state.modal == 'confirmDelete'} type="confirm" confirmButtonLabel="Delete File"
               onConfirmed={this.handleDeleteConfirmed} onAborted={this.closeModal}>
          Are you sure you'd like to delete <cite>{this.props.title}</cite>? This will {this.props.completed ? ' stop the download and ' : ''}
          permanently remove the file from your system.
        </Modal>
      </div>
    );
  }
});

var moreButtonColumnStyle = {
    height: '120px',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
  },
  moreButtonContainerStyle = {
    display: 'block',
    position: 'relative',
  },
  moreButtonStyle = {
    fontSize: '1.3em',
  },
  progressBarStyle = {
    height: '15px',
    width: '230px',
    backgroundColor: '#444',
    border: '2px solid #eee',
    display: 'inline-block',
  }, 
  artStyle = {
    maxHeight: '100px',
    maxWidth: '100%',
    display: 'block',
    marginLeft: 'auto',
    marginRight: 'auto',
  };
var MyFilesRow = React.createClass({
  onPauseResumeClicked: function() {
    if (this.props.stopped) {
      lbry.startFile(this.props.lbryUri);
    } else {
      lbry.stopFile(this.props.lbryUri);
    }
  },
  render: function() {
    //@TODO: Convert progress bar to reusable component

    var progressBarWidth = 230;

    if (this.props.completed) {
      var pauseLink = null;
      var curProgressBarStyle = {display: 'none'};
    } else {
      var pauseLink = <Link icon={this.props.stopped ? 'icon-play' : 'icon-pause'}
                            label={this.props.stopped ? 'Resume download' : 'Pause download'}
                            onClick={() => { this.onPauseResumeClicked() }} />;

      var curProgressBarStyle = Object.assign({}, progressBarStyle);
      curProgressBarStyle.width = Math.floor(this.props.ratioLoaded * progressBarWidth) + 'px';
      curProgressBarStyle.borderRightWidth = progressBarWidth - Math.ceil(this.props.ratioLoaded * progressBarWidth) + 2;
    }

    if (this.props.showWatchButton) {
      var watchButton = <WatchLink streamName={this.props.lbryUri} />
    } else {
      var watchButton = null;
    }

    return (
      <section className="card">
        <div className="row-fluid">
          <div className="span3">
            <Thumbnail src={this.props.imgUrl} alt={'Photo for ' + this.props.title} style={artStyle} />
          </div>
          <div className="span8">
            <h3>{this.props.pending ? this.props.title : <a href={'/?show=' + this.props.lbryUri}>{this.props.title}</a>}</h3>
            {this.props.pending ? <em>This file is pending confirmation</em>
              : (
               <div>
                 <div className={this.props.completed ? 'hidden' : ''} style={curProgressBarStyle}></div>
                 { ' ' }
                 {this.props.completed
                   ? (this.props.isMine
                      ? 'Published'
                      : 'Download complete')
                   : (parseInt(this.props.ratioLoaded * 100) + '%')}
                 <div>{ pauseLink }</div>
                 <div>{ watchButton }</div>
               </div>
             )
            }
          </div>
          <div className="span1" style={moreButtonColumnStyle}>
            {this.props.pending ? null :
             <div style={moreButtonContainerStyle}>
               <Link style={moreButtonStyle} ref="moreButton" icon="icon-ellipsis-h" title="More Options" />
               <MyFilesRowMoreMenu toggleButton={this.refs.moreButton} title={this.props.title}
                                   completed={this.props.completed} lbryUri={this.props.lbryUri}
                                   fileName={this.props.fileName} path={this.props.path}/>
             </div>
            }
          </div>
        </div>
      </section>
    );
  }
});

var MyFilesPage = React.createClass({
  _fileTimeout: null,
  _fileInfoCheckRate: 300,
  _fileInfoCheckNum: 0,
  _filesOwnership: {},

  getInitialState: function() {
    return {
      filesInfo: null,
      filesOwnershipLoaded: false,
      filesAvailable: {},
    };
  },
  getDefaultProps: function() {
    return {
      show: null,
    };
  },
  componentDidMount: function() {
    document.title = "My Files";
  },
  componentWillMount: function() {
    this.getFilesOwnership();
    this.updateFilesInfo();
  },
  componentWillUnmount: function() {
    if (this._fileTimeout)
    {
      clearTimeout(this._fileTimeout);
    }
  },
  getFilesOwnership: function() {
    lbry.getFilesInfo((filesInfo) => {
      if (!filesInfo) {
        this.setState({
          filesOwnershipLoaded: true,
        });
        return;
      }

      var ownershipLoadedCount = 0;
      for (let i = 0; i < filesInfo.length; i++) {
        let fileInfo = filesInfo[i];
        lbry.call('get_my_claim', {name: fileInfo.lbry_uri}, (claim) => {
          this._filesOwnership[fileInfo.lbry_uri] = !!claim;
          ownershipLoadedCount++;
          if (ownershipLoadedCount >= filesInfo.length) {
            this.setState({
              filesOwnershipLoaded: true,
            });
          }
        }, (claim) => {
          this._filesOwnership[fileInfo.lbry_uri] = true;
          ownershipLoadedCount++;
          if (ownershipLoadedCount >= filesInfo.length) {
            this.setState({
              filesOwnershipLoaded: true,
            });
          }
        });
      }
    });
  },
  updateFilesInfo: function() {
    lbry.getFilesInfo((filesInfo) => {
      if (!filesInfo) {
        filesInfo = [];
      }

      let newFilesAvailable;
      if (!(this._fileInfoCheckNum % this._fileInfoCheckRate)) {
        // Time to update file availability status

        newFilesAvailable = {};
        let filePeersCheckCount = 0;
        for (let fileInfo of filesInfo) {
          lbry.getPeersForBlobHash(fileInfo.sd_hash, (peers) => {
            filePeersCheckCount++;
            newFilesAvailable[fileInfo.sd_hash] = peers.length >= 0;
            if (filePeersCheckCount >= filesInfo.length) {
              this.setState({
                filesAvailable: newFilesAvailable,
              });
            }
          });
        }
      }

      this._fileInfoCheckNum += 1;

      this.setState({
        filesInfo: filesInfo,
      });

      this._fileTimeout = setTimeout(() => { this.updateFilesInfo() }, 1000);
    });
  },
  render: function() {
    if (this.state.filesInfo === null || !this.state.filesOwnershipLoaded) {
      return (
        <main className="page">
          <BusyMessage message="Loading" />
        </main>
      );
    }

    if (!this.state.filesInfo.length) {
      var content = <span>You haven't downloaded anything from LBRY yet. Go <Link href="/" label="search for your first download" />!</span>;
    } else {
      var content = [],
          seenUris = {};

      for (let fileInfo of this.state.filesInfo) {
        let {completed, written_bytes, total_bytes, lbry_uri, file_name, download_path,
          stopped, metadata, sd_hash} = fileInfo;

        var isMine = this._filesOwnership[lbry_uri];

        if (!metadata || seenUris[lbry_uri] || (this.props.show == 'downloaded' && isMine) ||
            (this.props.show == 'published' && !isMine)) {
          continue;
        }

        seenUris[lbry_uri] = true;

        let {title, thumbnail} = metadata;

        if (!fileInfo.pending && typeof metadata == 'object') {
          var {title, thumbnail} = metadata;
          var pending = false;
        } else {
          var title = null;
          var thumbnail = null;
          var pending = true;
        }

        var ratioLoaded = written_bytes / total_bytes;

        var mediaType = lbry.getMediaType(metadata.content_type, file_name);
        var showWatchButton = (mediaType == 'video');

        content.push(<MyFilesRow key={lbry_uri} lbryUri={lbry_uri} title={title || ('lbry://' + lbry_uri)} completed={completed} stopped={stopped}
                                 ratioLoaded={ratioLoaded} imgUrl={thumbnail} path={download_path}
                                 showWatchButton={showWatchButton} pending={pending}
                                 available={this.state.filesAvailable[sd_hash]} isMine={isMine} />);
      }
    }
    return (
      <main className="page">
        {content}
      </main>
    );
  }
});


export default MyFilesPage;