import React from 'react';
import {Actions} from 'nylas-exports';
import {RetinaImg} from 'nylas-component-kit';

import EmojiStore from './emoji-store';
import EmojiActions from './emoji-actions';
import emoji from 'node-emoji';
import categorizedEmojiList from './categorized-emoji';
import missingEmojiList from './missing-emoji';

class EmojiButtonPopover extends React.Component {
  static displayName = 'EmojiButtonPopover';

  constructor() {
    super();
    const {categoryNames,
      categorizedEmoji,
      categoryPositions} = this.getStateFromStore();
    this.state = {
      emojiName: "Emoji Picker",
      categoryNames: categoryNames,
      categorizedEmoji: categorizedEmoji,
      categoryPositions: categoryPositions,
      searchValue: "",
      activeTab: Object.keys(categorizedEmoji)[0],
    };
  }

  componentDidMount() {
    this._mounted = true;
    this.renderCanvas();
  }

  componentWillUnmount() {
    this._mounted = false;
  }

  onMouseDown = (event) => {
    const emojiName = this.calcEmojiByPosition(this.calcPosition(event));
    if (!emojiName) return null;
    EmojiActions.selectEmoji({emojiName, replaceSelection: false});
    Actions.closePopover();
  }

  onScroll = () => {
    const emojiContainer = document.querySelector(".emoji-finder-container");
    const tabContainer = document.querySelector(".emoji-tabs");
    tabContainer.className = emojiContainer.scrollTop ? "emoji-tabs shadow" : "emoji-tabs";
    if (emojiContainer.scrollTop === 0) {
      this.setState({activeTab: Object.keys(this.state.categorizedEmoji)[0]});
    } else {
      for (const category in this.state.categoryPositions) {
        if (this.state.categoryPositions.hasOwnProperty(category)) {
          if (emojiContainer.scrollTop >= this.state.categoryPositions[category].top &&
            emojiContainer.scrollTop <= this.state.categoryPositions[category].bottom) {
            if (category === 'More People') {
              this.setState({activeTab: 'People'});
            } else {
              this.setState({activeTab: category});
            }
          }
        }
      }
    }
  }

  onHover = (event) => {
    const emojiName = this.calcEmojiByPosition(this.calcPosition(event));
    if (emojiName) {
      this.setState({emojiName: emojiName});
    } else {
      this.setState({emojiName: "Emoji Picker"});
    }
  }

  onMouseOut = () => {
    this.setState({emojiName: "Emoji Picker"});
  }

  onChange = (event) => {
    const searchValue = event.target.value;
    if (searchValue.length > 0) {
      const searchMatches = this.findSearchMatches(searchValue);
      this.setState({
        categorizedEmoji: {
          'Search Results': searchMatches,
        },
        categoryPositions: {
          'Search Results': {
            top: 25,
            bottom: 25 + Math.ceil(searchMatches.length / 8) * 24,
          },
        },
        searchValue: searchValue,
        activeTab: null,
      }, this.renderCanvas);
    } else {
      this.setState(this.getStateFromStore, () => {
        this.setState({
          searchValue: searchValue,
          activeTab: Object.keys(this.state.categorizedEmoji)[0],
        }, this.renderCanvas);
      });
    }
  }

  getStateFromStore = () => {
    let categorizedEmoji = categorizedEmojiList;
    const categoryPositions = {};
    let categoryNames = [
      'People',
      'More People',
      'Nature',
      'Food and Drink',
      'Activity',
      'Travel and Places',
      'Objects',
      'Symbols',
      'Flags',
    ];
    const frequentlyUsedEmoji = EmojiStore.frequentlyUsedEmoji();
    if (frequentlyUsedEmoji.length > 0) {
      categorizedEmoji = {'Frequently Used': frequentlyUsedEmoji};
      for (const category in categorizedEmojiList) {
        if (categorizedEmojiList.hasOwnProperty(category)) {
          categorizedEmoji[category] = categorizedEmojiList[category];
        }
      }
      categoryNames = ["Frequently Used"].concat(categoryNames);
    }
    for (const name of categoryNames) {
      categoryPositions[name] = {top: 0, bottom: 0};
    }
    let verticalPos = 25;
    for (const category in categoryPositions) {
      if (categoryPositions.hasOwnProperty(category)) {
        const height = Math.ceil(categorizedEmoji[category].length / 8) * 24;
        categoryPositions[category].top = verticalPos;
        verticalPos += height;
        categoryPositions[category].bottom = verticalPos;
        if (category !== 'People') {
          verticalPos += 24;
        }
      }
    }
    return {
      categoryNames: categoryNames,
      categorizedEmoji: categorizedEmoji,
      categoryPositions: categoryPositions,
    };
  }

  scrollToCategory(category) {
    const container = document.querySelector(".emoji-finder-container");
    if (this.state.searchValue.length > 0) {
      this.setState({searchValue: ""});
      this.setState(this.getStateFromStore, () => {
        this.renderCanvas();
        container.scrollTop = this.state.categoryPositions[category].top + 16;
      });
    } else {
      container.scrollTop = this.state.categoryPositions[category].top + 16;
    }
    this.setState({activeTab: category})
  }

  findSearchMatches(searchValue) {
    const searchMatches = [];
    for (const category of Object.keys(categorizedEmojiList)) {
      categorizedEmojiList[category].forEach((emojiName) => {
        if (emojiName.indexOf(searchValue) !== -1) {
          searchMatches.push(emojiName);
        }
      });
    }
    return searchMatches;
  }

  calcPosition = (event) => {
    const rect = event.target.getBoundingClientRect();
    const position = {
      x: event.pageX - rect.left / 2,
      y: event.pageY - rect.top / 2,
    };
    return position;
  }

  calcEmojiByPosition = (position) => {
    for (const category in this.state.categoryPositions) {
      if (this.state.categoryPositions.hasOwnProperty(category)) {
        const LEFT_PADDING = 8;
        const RIGHT_PADDING = 204;
        const EMOJI_WIDTH = 24.5;
        const EMOJI_HEIGHT = 24;
        const EMOJI_PER_ROW = 8;
        if (position.x >= LEFT_PADDING &&
            position.x <= RIGHT_PADDING &&
            position.y >= this.state.categoryPositions[category].top &&
            position.y <= this.state.categoryPositions[category].bottom) {
          const x = Math.round((position.x + 5) / EMOJI_WIDTH);
          const y = Math.round((position.y - this.state.categoryPositions[category].top + 10) / EMOJI_HEIGHT);
          const index = x + (y - 1) * EMOJI_PER_ROW - 1;
          return this.state.categorizedEmoji[category][index];
        }
      }
    }
    return null;
  }

  renderTabs() {
    const tabs = [];
    this.state.categoryNames.forEach((category) => {
      if (category !== 'More People') {
        let className = `emoji-tab ${(category.replace(/ /g, '-')).toLowerCase()}`
        if (category === this.state.activeTab) {
          className += " active";
        }
        tabs.push(
          <div key={`${category} container`} style={{flex: 1}}>
            <RetinaImg
              key={`${category} tab`}
              className={className}
              name={`icon-emojipicker-${(category.replace(/ /g, '-')).toLowerCase()}.png`}
              mode={RetinaImg.Mode.ContentIsMask}
              onMouseDown={() => this.scrollToCategory(category)} />
          </div>
        );
      }
    });
    return tabs;
  }

  renderCanvas() {
    const canvas = document.getElementById("emoji-canvas");
    const keys = Object.keys(this.state.categoryPositions);
    canvas.height = this.state.categoryPositions[keys[keys.length - 1]].bottom * 2;
    const ctx = canvas.getContext("2d");
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    const position = {
      x: 15,
      y: 45,
    }
    Object.keys(this.state.categorizedEmoji).forEach((category, i) => {
      if (i > 0) {
        setTimeout(() => this.renderCategory(category, i, ctx, position), i * 50);
      } else {
        this.renderCategory(category, i, ctx, position);
      }
    });
  }

  renderCategory(category, i, ctx, position) {
    if (!this._mounted) return;
    if (category !== "More People") {
      if (i > 0) {
        position.x = 18;
        position.y += 48;
      }
      ctx.font = "24px Nylas-Pro";
      ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
      ctx.fillText(category, position.x, position.y);
    }
    position.x = 18;
    position.y += 48;
    ctx.font = "32px Arial";
    ctx.fillStyle = 'black';
    this.state.categorizedEmoji[category].forEach((emojiName, j) => {
      if (missingEmojiList.indexOf(emojiName) === -1) {
        const emojiChar = emoji.get(emojiName);
        ctx.fillText(emojiChar, position.x, position.y);
      } else {
        const img = new Image();
        img.src = `images/composer-emoji/missing-emoji/${emojiName}.png`;
        const x = position.x;
        const y = position.y;
        img.onload = () => {
          ctx.drawImage(img, x, y - 30, 32, 32);
        }
      }
      if (position.x > 325 && j < this.state.categorizedEmoji[category].length - 1) {
        position.x = 18;
        position.y += 48;
      } else {
        position.x += 50;
      }
    })
  }

  render() {
    return (
      <div className="emoji-button-popover" tabIndex="-1">
        <div className="emoji-tabs">
          {this.renderTabs()}
        </div>
        <div
          className="emoji-finder-container"
          onScroll={this.onScroll}>
          <div className="emoji-search-container">
            <input
              type="text"
              className="search"
              value={this.state.searchValue}
              onChange={this.onChange}
            />
          </div>
          <canvas
            id="emoji-canvas"
            width="420"
            height="2000"
            onMouseDown={this.onMouseDown}
            onMouseOut={this.onMouseOut}
            onMouseMove={this.onHover}
            style={{zoom: "0.5"}}>
          </canvas>
        </div>
        <div className="emoji-name">
          {this.state.emojiName}
        </div>
      </div>
    );
  }
}

export default EmojiButtonPopover;
