import React from 'react';
import Ticker from 'components/ui/Ticker';
import moment from 'moment';
import get from 'lodash/get';
import classnames from 'classnames';
import Levenshtein from 'levenshtein';
import { channelService } from '../../../services';
import { openSecurity } from 'actions/workspaces';
import { hueToColor } from 'utils/html';

export default class FeedStory extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      title: props.story.Title || '',
      body: this.partnerBody(props.story) || '',
      partnerURL: props.story.PartnerURL || '',
      timestamp: props.story.Timestamp,
      ticker: props.story.Ticker,
      openBody: false
    };
    this.toggleBody = this.toggleBody.bind(this);
  }

  onBodyLinkClick(event) {
    const hrefValue = event.target.href;
    const symbol = event.target.innerText;
    const securityPatternPre = /\((NASDAQ|NYSE|NYSEMKT|OTCMKTS|AMEX|TSX): $/i;
    const securityPatternPost = /^\)/i;

    const prevSib = event.target.previousSibling;
    const nextSib = event.target.nextSibling;

    if (event.target.tagName === 'A' &&
        ((prevSib && securityPatternPre.test(prevSib.textContent)) &&
        (nextSib && securityPatternPost.test(nextSib.textContent)))) {
      event.preventDefault();
      event.stopPropagation();
      openSecurity(symbol);
    } else if (hrefValue) {
      event.preventDefault();

      // Chrome doesn't support tabs if any settings are passed. Must use _blank
      // ToDo: Eventually replace this with a library of browsers, os and mobile...
      if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
        window.open(hrefValue, '_blank');
      } else {
        // Set the default toolbar
        const name    = '_blank';
        // let toolBar = 'location=yes, menubar=yes, toolbar=yes, scrollbars=yes, resizable=yes';
        let toolBar = 'resizable=yes,scrollbars=yes,toolbar=yes,menubar=no,location=no,directories=no,status=1,statusbar=1';
        let width   = 800;
        let height  = 600;

        // Check the screen size to determin if we add window size.  Could use device.
        if (screen.width >= width && screen.height >= height) {
          // Set the new window position relative to this window
          toolBar = toolBar + ', top=' + (window.screenY + 50) + ', left=' + (window.screenX + 50);

          // If the primary window is big enough, set this relative
          if (window.innerWidth > 800 && window.innerHeight > 600) {
            height = window.innerHeight - 100;
            width  = window.innerWidth - 100;
          }

          toolBar = toolBar + ', width=' + width + ', height=' + height;
        }

        window.open(hrefValue, name, toolBar);
      }
    }
  }

  getRawTitle() {
    return {__html: this.state.title};
  }

  partnerLink(partnerURL) {
    const link = document.createElement('a');
    link.innerText = 'Read more...';
    link.href = partnerURL;
    link.target = '_blank';
    return '<br/><div>' + link.outerHTML + '</div>';
  }

  // Turn plaintext links into hyperlinks.
  injectLinks(originalBody) {
    // Matches things starting with http:// (or https), followed by at least one
    // character allowed in URLs. The matched string cannot be followed by an
    // unpaired closing angle bracket, since if it was its likely that the URL
    // is an attribute inside an HTML tag.
    const untaggedUrlRegex = /https?:\/\/[#$&-;=?-\[\]_a-z~]+(?![^<]*>)/gi;
    const newBody = originalBody.replace(untaggedUrlRegex, url => {
      return '<a href="' + url + '">' + url + '</a>';
    });
    return newBody;
  }

  partnerBody(story) {
    const partnerURL = story.PartnerURL;
    const body = story.Body;

    // No partner link? Just return body.
    if (!partnerURL || partnerURL.length < 1) {
      return body;
    }

    const title = story.Title;
    const l = new Levenshtein(body, title);
    if (l.distance >= 15) {
      // The body and title are different. Append a link.
      return body + '...' + this.partnerLink(partnerURL);
    }
    // The body and the title are the same. Just put the link in.
    return this.partnerLink(partnerURL);
  }

  sentimentClass() {
    switch (this.props.story.Sentiment) {
    case -3:
      return 'sentiment-bear sentiment-triple';
    case -2:
      return 'sentiment-bear sentiment-double';
    case -1:
      return 'sentiment-bear sentiment-single';
    case 1:
      return 'sentiment-bull sentiment-single';
    case 2:
      return 'sentiment-bull sentiment-double';
    case 3:
      return 'sentiment-bull sentiment-triple';
    case 0:
      return 'sentiment-neutral';
    default:
      return 'sentiment-none';
    }
  }

  toggleBody(event) {
    if (!('href' in event.target) && event.button === 0 && document.getSelection().isCollapsed) {
      const parentOffset = this.refs.article.parentElement.getBoundingClientRect().top;
      const thisOffset = this.refs.article.getBoundingClientRect().top;
      const posRelToFeed = thisOffset - parentOffset;
      if (posRelToFeed < 0) {
        this.refs.article.parentElement.scrollTop += posRelToFeed;
      }
      if (this.state.openBody) {
        this.props.onBodyClose(event, this.refs.article);
      }
      this.setState({openBody: !this.state.openBody});
      bzTrack.track('Feed: Story Clicked', {
        title: this.props.story.Title,
        nodeID: this.props.story.NodeID
      });
    }
  }

  popoutStory() {
    if (this.state.partnerURL) {
      const w = window.open(this.state.partnerURL, '_blank');
      bzTrack.track('Feed: Partner Story Opened New Window', {
        title: this.props.story.Title,
        nodeID: this.props.story.NodeID
      });
    } else if (this.state.body) {
      const w = window.open('', '', 'width=800, height=800, scrollbars=yes, resizable=yes');
      const pageTitle = '<title>' + this.props.story.Title + '</title>';
      const fonts = "<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,700|Lora:400,400italic,700,700italic' rel='stylesheet' type='text/css'>";
      const style = "<style>body{font-size:18px;line-height:1.55em;padding:1em 5.5%;max-width:700px;margin:0 auto;font-family: 'Lora', serif;}p{font-size:1em;margin-bottom:1.55em}h1{font-family: 'Open Sans', sans-serif;font-size:2em;line-height:1.25em;font-weight: 600}h2,h3,h4,h5,h6{font-size:1em;font-weight:600}a{color:#2D86C3}object{display:none}</style>";
      const head = '<head>' + pageTitle + fonts + style + '</head>';
      const storyTitle = '<h1>' + this.props.story.Title + '</h1>';
      const body = '<body>' + storyTitle + this.state.body + '</body>';
      const page = '<html>' + head + body + '</html>';
      w.document.open().write(page);
      bzTrack.track('Feed: Story Opened New Window', {
        title: this.props.story.Title,
        nodeID: this.props.story.NodeID
      });
    }
  }

  renderBody() {
    const { openBody, body, story } = this.state;
    const modifiedBody = this.injectLinks(body);
    const bodyClass = classnames('FeedStory-content__body', {'FeedStory-content__body--open': openBody});
    // To save DOM resources, only set the body when open.
    if (openBody && (body.trim().length || channelService.isPressReleaseType(this.props.story.Type))) {
      return (
        <div className={bodyClass} onClick={(e) => this.onBodyLinkClick(e)} dangerouslySetInnerHTML={{__html: modifiedBody}} />
      );
    }
    return '';
  }
  render() {
    const hasBody = this.state.body.trim().length;
    const visuallyExpandable = hasBody ? <span className="FeedStory-readmore">[+]</span> : null;
    const contentClass = classnames('FeedStory-content', {'FeedStory-content--hasbody': hasBody});
    // (maximumSize - currentSize) * scalar
    const widthMod = (16 - this.props.textSize) * 4;
    const storyStyle = {};
    if (this.props.theme) {
      storyStyle.backgroundColor = hueToColor(this.props.theme.hue);
    }
    storyStyle.padding = this.props.headerSpacing !== undefined ? this.props.headerSpacing + 'px 0px' : '1.7px 0px';

    return (
      <article ref="article" className={classnames('FeedStory', {'FeedStory__live': this.props.story.Live})} style={storyStyle}>
        <div className="FeedStory-time" style={{width: (85 - widthMod) + 'px'}}>
          {moment(+moment.utc(this.props.story.CreatedAt)).format('h:mm:ssa')}
        </div>
        <div className="FeedStory-symbols" style={{width: (65 - widthMod) + 'px'}}>
          {this.props.story.Tickers && this.props.story.Tickers.map((ticker, i) =>
            i < 1 && ticker.name.length < 8 ? <Ticker symbol={ticker.name} publishQuote={get(this.props.story.Quotes, ticker.name)} key={i}/> : null
          )}
        </div>
        <div className={classnames('FeedStory-sentiment', this.sentimentClass())}>
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="-288.815 386.754 6.766 16">
              <path className="sentiment-arrow sentiment-arrow--one" fill="#50C773" d="M-282.55 390.456c-.116 0-.234-.04-.33-.125l-2.55-2.244-2.555 2.246c-.207.183-.522.162-.705-.044-.183-.207-.162-.523.045-.706l3.214-2.827 3.21 2.827c.21.183.23.5.045.706-.098.113-.236.17-.375.17z"/>
              <path className="sentiment-arrow sentiment-arrow--two" fill="#50C773" d="M-282.55 396.605c-.116 0-.234-.04-.33-.125l-2.55-2.246-2.555 2.246c-.207.183-.522.162-.705-.045s-.162-.523.045-.706l3.214-2.83 3.21 2.828c.21.182.23.498.045.705-.098.113-.236.17-.375.17z"/>
              <path className="sentiment-arrow sentiment-arrow--three" fill="#50C773" d="M-288.314 402.754c-.14 0-.276-.058-.375-.17-.18-.207-.16-.523.047-.705l3.214-2.83 3.213 2.828c.208.18.228.497.045.704-.182.208-.498.23-.705.045l-2.552-2.246-2.553 2.246c-.095.083-.213.124-.33.124z"/>
          </svg>
        </div>
        <div className={contentClass} onClick={(e) => this.toggleBody(e)} onDoubleClick={() => this.popoutStory()}>
          <p className="FeedStory-content__title">
            <span dangerouslySetInnerHTML={this.getRawTitle()}></span> {visuallyExpandable}
          </p>
          {this.renderBody()}
        </div>
        <div className="FeedStory-tag">
          {channelService.storyToShortName(this.props.story)}
        </div>
      </article>
    );
  }
}

FeedStory.propTypes = {
  sentiment: React.PropTypes.number,
  headerSpacing: React.PropTypes.number,
  onBodyClose: React.PropTypes.func,
  story: React.PropTypes.object,
  textSize: React.PropTypes.number,
  theme: React.PropTypes.object
};
