import moment from 'moment';
import React from 'react';
import { Glyphicon } from 'react-bootstrap';
import {
  ANNOTATION,
  EVENT_CATEGORY_COMMANDLINE,
  EVENT_CATEGORY_COMMENT,
  EVENT_CATEGORY_DEBUG,
  EVENT_CATEGORY_ERROR,
  EVENT_CATEGORY_INFO,
  NOTIFICATION,
} from '../constants/eventTypes';

/**
 * Get the visual representation of the event's category. Ban cicle Glyph provided when there is no category
 * @param {*} category the event category
 * @param {string} size the size in px of the icon, 25 by default
 */
export function getEventIcon(category, size) {
  const iconSize = `${size || '25'}px`;
  if (category) {
    if (category.toLowerCase() === EVENT_CATEGORY_COMMENT) {
      return <img src="/comment.png" width={iconSize} alt="comment.png" />;
    } else if (category.toLowerCase() === EVENT_CATEGORY_COMMANDLINE) {
      return (
        <Glyphicon
          glyph="expand"
          style={{ fontSize: iconSize, position: 'static' }}
        />
      );
    } else if (category.toLowerCase() === EVENT_CATEGORY_ERROR) {
      return (
        <Glyphicon
          glyph="alert"
          style={{ fontSize: iconSize, color: '#d03436', position: 'static' }}
        />
      );
    } else if (category.toLowerCase() === EVENT_CATEGORY_INFO) {
      return (
        <Glyphicon
          glyph="info-sign"
          style={{ fontSize: iconSize, color: '#3366cc', position: 'static' }}
        />
      );
    } else if (category.toLowerCase() === EVENT_CATEGORY_DEBUG) {
      return (
        <Glyphicon
          glyph="exclamation-sign"
          style={{ fontSize: iconSize, color: 'gray', position: 'static' }}
        />
      );
    }
  }
  // no category was found
  return <Glyphicon glyph="ban-circle" style={{ fontSize: iconSize }} />;
}

/**
 * Get the formatted event creation date for an event history
 * @param {event} event the event to retrieve the creation date from
 * @returns {String} the formatted date under the from  MMM DD YYYY HH:mm a
 */
export function getEventHistoryCreationDate(event) {
  return moment(event.creationDate).format('MMM DD YYYY HH:mm:ss');
}

/**
 * Get the original event which the provided event has modified. This original event is the more nested event inside the provided event.
 * @param {event} event the event which has modified the original event.
 * @return {event} the original event. If there is no original event (ie the provided event is the original event) returns itself.
 */
export function getOriginalEvent(event) {
  let e = event;
  if (e) {
    while (e.previousVersionEvent) {
      e = e.previousVersionEvent;
    }
    return e;
  }
  return null;
}

/**
 * Get the original username for the given event.
 * @param {*} event the event under investigation
 * @returns {string} the original username, null if not found
 */
export function getOriginalUsername(event) {
  const originalEvent = getOriginalEvent(event);
  return originalEvent.username ? originalEvent.username : null;
}

/**
 * Get the number of previous version an given event has.
 * @param {event} event the event which is investigated
 * @returns {number} the number of previous event version which exists
 */
export function getPreviousVersionNumber(event) {
  let e = event;
  if (e) {
    let previousVersionNumber = 0;
    while (e.previousVersionEvent) {
      previousVersionNumber += 1;
      e = e.previousVersionEvent;
    }
    return previousVersionNumber;
  }
  return 0;
}

/**
 * Get the text from a given event content
 * @param {array} content
 * @param {string} format the requested format ('plainText', 'html' )
 * @returns {string} the text of content. Null if not found.
 */
export function getContent(content, format) {
  if (content) {
    for (const item of content) {
      if (item.format) {
        if (item.format === format) {
          if (item.text) {
            return item.text;
          }
        }
      }
    }
  }
  return null;
}

/**
 * Gets the content of the event as an html string.
 * @param {array} the event content, not null
 * @returns {string} If the HTML format exists, returns the content in HTML format. If not, returns the plainText formatted content surrounded by <p> </p>. Null if no format exist.
 */
export function getContentAsHTML(content) {
  const HTMLText = getContent(content, 'html');
  if (HTMLText) {
    return HTMLText;
  }
  const plainText = getContent(content, 'plainText');
  if (plainText) {
    return `<p>${plainText}</p>`;
  }

  return null;
}

/**
 * Get the last comment of an event
 * @param {*} event
 * @returns {array} the content of the comment in all different formats available
 */
export function getLastCommentContent(event) {
  if (event) {
    if (event.type) {
      if (event.type === ANNOTATION) {
        return event.content;
      } else if (event.type === NOTIFICATION) {
        const nbPreviousVersion = getPreviousVersionNumber(event);
        if (nbPreviousVersion > 0) {
          return event.content;
        }
      }
    }
  }
  return null;
}

/**
 * Converts images to thumbnails
 * @param {String} html text containing an HTML node possibly including <img/> elements
 * @returns {String} text containing the same HTML node as the input where each img element as been modified to make the image look like a thumbnail
 */
export function convertImagesToThumbnails(html) {
  if (html) {
    return html.replace(
      new RegExp('img src', 'g'),
      'img style="height:200px;width:auto;cursor:zoom-in;" src'
    );
  }
}

/**
 * Get the first letters of the event content.
 * @param {array} content the event content
 * @param {integer} nbCharacterToDisplay the number of characters to be returned
 * @returns {string} the portion of plain text composed of the nbCharacterToDisplay first characters
 */
export function getFirstLettersofContent(content, nbCharacterToDisplay) {
  const text = getContent(content, 'plainText');
  if (text) {
    if (nbCharacterToDisplay) {
      if (text.length > nbCharacterToDisplay) {
        return `${text.slice(0, nbCharacterToDisplay)} ...`;
      }
      return text.slice(0, nbCharacterToDisplay);
    }
    return `${text.slice(0, 10)} ...`;
  }

  return '';
}

/**
 * HTTP error parser. THis is meant to handle HTTP error such as 400, 403, 404 creating a general error message for these types of errors.
 * @param {*} error HTTP error
 * @returns {String} Error message
 */
export function parseHTTPError(error) {
  if (error) {
    if (error.response) {
      if (error.response.status === 403) {
        return 'You do not have the permission to access this resource.';
      }
    }
  }
  return 'An error has occured.';
}

/**
 * Get the sorting order
 * @param {object} sortingFilter sorting filter. Example: { creationDate: 1 }
 * @returns {number} the sorting order (1 or -1) for the field the events are sorted by. 1 => ascending; -1 => descending; -1 if not properly setup
 */
export function getSortingOrder(sortingFilter) {
  if (sortingFilter) {
    const sortingOrder = sortingFilter[Object.keys(sortingFilter)[0]];

    if (sortingOrder === 1 || sortingOrder === -1) {
      return sortingOrder;
    }
    return -1;
  }
}
