<commit_before>import * as React from 'react';
import * as _ from 'lodash';
import * as events from '@csegames/camelot-unchained/lib/events';
import styled, { css } from 'react-emotion';

import eventNames, { EquipItemPayload, InventoryDataTransfer, EquippedItemDataTransfer } from '../../../lib/eventNames';
import { defaultSlotIcons, placeholderIcon } from '../../../lib/constants';
import { getEquippedDataTransfer, hasEquipmentPermissions } from '../../../lib/utils';
import withDragAndDrop, { DragAndDropInjectedProps, DragEvent } from '../../../../../components/DragAndDrop/DragAndDrop';
import {
  InventoryItem,
  EquippedItem,
  GearSlotDefRef,
} from 'gql/interfaces';

declare const toastr: any;

const Container = styled('div')`
  position: relative;
  width: 100%;
  height: 100%;
  opacity: ${(props: any) => props.opacity};
`;

const ItemIcon = styled('img')`
  width: 100%;
  height: 100%;
`;

const SlotOverlay = styled('div')`
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: ${(props: any) => props.backgroundColor};
  box-shadow: ${(props: any) => props.boxShadow};
  border: 1px solid transparent;
  &:hover {
    box-shadow: inset 0 0 10px rgba(255,255,255,0.2);
  }
  &:active {
    box-shadow: inset 0 0 10px rgba(0,0,0,0.4);
  }
  &.highlight-slot {
    box-shadow: inset 0 0 10px 2px rgba(255, 218, 148, 0.7);
    border: 1px solid rgba(255, 218, 148, 1);
  }
  &.item-menu-visible {
    border: 1px solid #e1b96d;
    box-shadow: inset 0 0 10px rgba(255,255,255,0.2);
  }
`;

const defaultIconStyle = css`
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.15;
  width: 100%;
  height: 100%;
  color: #CFD0CB;
  font-size: 35px;
`;

export interface DraggableEquippedItemProps extends DragAndDropInjectedProps {
  slotName: string;
  disableDrag: boolean;
  itemMenuVisible: boolean;
  equippedItem: EquippedItem.Fragment;
}

export interface DraggableEquippedItemState {
  opacity: number;
  backgroundColor: string;
  highlightSlot: boolean;
}

const colors = {
  canEquip: 'rgba(46, 213, 80, 0.4)',
  cannotEquip: 'rgba(186, 50, 50, 0.4)',
};

class EquippedItemComponent extends React.Component<DraggableEquippedItemProps, DraggableEquippedItemState> {
  private onHighlightListener: number;
  private onDehighlightListener: number;

  constructor(props: DraggableEquippedItemProps) {
    super(props);
    this.state = {
      opacity: 1,
      backgroundColor: 'transparent',
      highlightSlot: false,
    };
  }

  public data() {
    const equippedItem = this.props.equippedItem;
    return getEquippedDataTransfer({
      item: equippedItem.item,
      location: 'equipped',
      position: -1,
      gearSlots: equippedItem.gearSlots,
    });
  }

  public onDragStart() {
    this.setState({ opacity: 0.3 });
  }

  public onDrop(e: DragEvent<InventoryDataTransfer, DraggableEquippedItemProps>) {
    const item = { ...e.dataTransfer.item };
    const { ok, reason } = this.canEquip(item);
    if (ok && item.location.inventory) {
      item.location.inventory = null;
      this.equipItem(e.dataTransfer, this.props.equippedItem);
    } else if (ok && !item.location.inventory) {
      this.equipItem(e.dataTransfer, this.props.equippedItem);
    } else if (!ok) {
      if (reason) {
        toastr.error(reason, 'Oh No!', { timeout: 3000 });
      } else {
        toastr.error('You cannot equip this item', 'Oh No!', { timeout: 3000 });
      }
    }
  }

  public onDragOver(e: DragEvent<InventoryDataTransfer, DraggableEquippedItemProps>) {
    if (this.state.backgroundColor === 'transparent') {
      const { ok } = this.canEquip(e.dataTransfer.item as any);
      if (ok) {
        this.setState({ backgroundColor: colors.canEquip });
      } else {
        this.setState({ backgroundColor: colors.cannotEquip });
      }
    }
  }

  public onDragLeave() {
    this.setState({ backgroundColor: 'transparent' });
  }

  public onDragEnd() {
    this.setState({ opacity: 1 });
  }

  public render() {
    const { equippedItem, slotName, itemMenuVisible } = this.props;
    const iconUrl = (equippedItem && equippedItem.item.staticDefinition && equippedItem.item.staticDefinition.iconUrl) ||
      `${defaultSlotIcons[slotName]} \ ${defaultIconStyle}`;
    const isRightSlot = _.includes(slotName.toLowerCase(), 'right');
    const flipIcon = isRightSlot ? { transform: 'scaleX(-1)', WebkitTransform: 'scaleX(-1)' } : {};
    return (
      <Container opacity={this.state.opacity}>
        {this.props.equippedItem ? <ItemIcon style={flipIcon} src={iconUrl || placeholderIcon} /> :
          <div style={flipIcon} className={`${iconUrl}`} />}
        <SlotOverlay
          className={`${itemMenuVisible ? 'item-menu-visible' : ''} ${this.state.highlightSlot ? 'highlight-slot' : ''}`}
          backgroundColor={this.state.backgroundColor}
        />
      </Container>
    );
  }

  public componentDidMount() {
    this.onHighlightListener = events.on(eventNames.onHighlightSlots, this.onHighlightSlots);
    this.onDehighlightListener = events.on(eventNames.onDehighlightSlots, this.onDehighlightSlots);
  }

  public componentDidUpdate(prevProps: DraggableEquippedItemProps) {
    const prevEquippedItem = prevProps.equippedItem && prevProps.equippedItem.item;
    const equippedItem = this.props.equippedItem && this.props.equippedItem.item;
    if ((!prevEquippedItem && equippedItem && this.state.backgroundColor !== 'transparent') ||<commit_msg>Fix placeholder icons and equipped item icons not being same alignment<commit_after>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

import * as React from 'react';
import * as _ from 'lodash';
import * as events from '@csegames/camelot-unchained/lib/events';
import styled, { css } from 'react-emotion';

import eventNames, { EquipItemPayload, InventoryDataTransfer, EquippedItemDataTransfer } from '../../../lib/eventNames';
import { defaultSlotIcons, placeholderIcon } from '../../../lib/constants';
import { getEquippedDataTransfer, hasEquipmentPermissions } from '../../../lib/utils';
import withDragAndDrop, { DragAndDropInjectedProps, DragEvent } from '../../../../../components/DragAndDrop/DragAndDrop';
import {
  InventoryItem,
  EquippedItem,
  GearSlotDefRef,
} from 'gql/interfaces';

declare const toastr: any;

const Container = styled('div')`
  position: relative;
  width: 100%;
  height: 100%;
  opacity: ${(props: any) => props.opacity};
`;

const ItemIcon = styled('img')`
  width: 100%;
  height: 100%;
`;

const SlotOverlay = styled('div')`
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: ${(props: any) => props.backgroundColor};
  box-shadow: ${(props: any) => props.boxShadow};
  border: 1px solid transparent;
  &:hover {
    box-shadow: inset 0 0 10px rgba(255,255,255,0.2);
  }
  &:active {
    box-shadow: inset 0 0 10px rgba(0,0,0,0.4);
  }
  &.highlight-slot {
    box-shadow: inset 0 0 10px 2px rgba(255, 218, 148, 0.7);
    border: 1px solid rgba(255, 218, 148, 1);
  }
  &.item-menu-visible {
    border: 1px solid #e1b96d;
    box-shadow: inset 0 0 10px rgba(255,255,255,0.2);
  }
`;

const defaultIconStyle = css`
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.15;
  width: 100%;
  height: 100%;
  color: #CFD0CB;
  font-size: 35px;
`;

export interface DraggableEquippedItemProps extends DragAndDropInjectedProps {
  slotName: string;
  disableDrag: boolean;
  itemMenuVisible: boolean;
  equippedItem: EquippedItem.Fragment;
}

export interface DraggableEquippedItemState {
  opacity: number;
  backgroundColor: string;
  highlightSlot: boolean;
}

const colors = {
  canEquip: 'rgba(46, 213, 80, 0.4)',
  cannotEquip: 'rgba(186, 50, 50, 0.4)',
};

class EquippedItemComponent extends React.Component<DraggableEquippedItemProps, DraggableEquippedItemState> {
  private onHighlightListener: number;
  private onDehighlightListener: number;

  constructor(props: DraggableEquippedItemProps) {
    super(props);
    this.state = {
      opacity: 1,
      backgroundColor: 'transparent',
      highlightSlot: false,
    };
  }

  public data() {
    const equippedItem = this.props.equippedItem;
    return getEquippedDataTransfer({
      item: equippedItem.item,
      location: 'equipped',
      position: -1,
      gearSlots: equippedItem.gearSlots,
    });
  }

  public onDragStart() {
    this.setState({ opacity: 0.3 });
  }

  public onDrop(e: DragEvent<InventoryDataTransfer, DraggableEquippedItemProps>) {
    const item = { ...e.dataTransfer.item };
    const { ok, reason } = this.canEquip(item);
    if (ok && item.location.inventory) {
      item.location.inventory = null;
      this.equipItem(e.dataTransfer, this.props.equippedItem);
    } else if (ok && !item.location.inventory) {
      this.equipItem(e.dataTransfer, this.props.equippedItem);
    } else if (!ok) {
      if (reason) {
        toastr.error(reason, 'Oh No!', { timeout: 3000 });
      } else {
        toastr.error('You cannot equip this item', 'Oh No!', { timeout: 3000 });
      }
    }
  }

  public onDragOver(e: DragEvent<InventoryDataTransfer, DraggableEquippedItemProps>) {
    if (this.state.backgroundColor === 'transparent') {
      const { ok } = this.canEquip(e.dataTransfer.item as any);
      if (ok) {
        this.setState({ backgroundColor: colors.canEquip });
      } else {
        this.setState({ backgroundColor: colors.cannotEquip });
      }
    }
  }

  public onDragLeave() {
    this.setState({ backgroundColor: 'transparent' });
  }

  public onDragEnd() {
    this.setState({ opacity: 1 });
  }

  public render() {
    const { equippedItem, slotName, itemMenuVisible } = this.props;
    const iconUrl = (equippedItem && equippedItem.item.staticDefinition && equippedItem.item.staticDefinition.iconUrl) ||
      `${defaultSlotIcons[slotName]} \ ${defaultIconStyle}`;
    const isRightSlot = _.includes(slotName.toLowerCase(), 'left');
    const flipIcon = isRightSlot ? { transform: 'scaleX(-1)', WebkitTransform: 'scaleX(-1)' } : {};
    const flipSlotPlaceholderIcon = !isRightSlot ? { transform: 'scaleX(-1)', WebkitTransform: 'scaleX(-1)' } : {};
    return (
      <Container opacity={this.state.opacity}>
        {this.props.equippedItem ? <ItemIcon style={flipIcon} src={iconUrl || placeholderIcon} /> :
          <div style={flipSlotPlaceholderIcon} className={`${iconUrl}`} />}
        <SlotOverlay
          className={`${itemMenuVisible ? 'item-menu-visible' : ''} ${this.state.highlightSlot ? 'highlight-slot' : ''}`}
          backgroundColor={this.state.backgroundColor}
        />
      </Container>
    );
  }

  public componentDidMount() {
    this.onHighlightListener = events.on(eventNames.onHighlightSlots, this.onHighlightSlots);
    this.onDehighlightListener = events.on(eventNames.onDehighlightSlots, this.onDehighlightSlots);
  }

  public componentDidUpdate(prevProps: DraggableEquippedItemProps) {
    const prevEquippedItem = prevProps.equippedItem && prevProps.equippedItem.item;
    const equippedItem = this.props.equippedItem && this.props.equippedItem.item;
    if ((!prevEquippedItem && equippedItem && this.state.backgroundColor !== 'transparent') ||
{'fraction_non_alphanumeric': 0.1416225749559083, 'fraction_numerical': 0.023809523809523808, 'mean_word_length': 3.665158371040724, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6444867', 'n_tokens_mistral': 3871, 'n_tokens_neox': 3626, 'n_words': 806}