import React, { Fragment, useState, useEffect, useRef, useCallback } from 'react';
import { injectIntl, FormattedMessage } from 'react-intl';
import get from 'lodash/get';
import moment from 'moment';
import CapInput from '@capillarytech/cap-ui-library/CapInput';
import CapUploader from '@capillarytech/cap-ui-library/CapUploader';
import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
import CapButton from '@capillarytech/cap-ui-library/CapButton';
import CapDrawer from '@capillarytech/cap-ui-library/CapDrawer';
import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
import CapError from '@capillarytech/cap-ui-library/CapError';
import CapRadioGroup from '@capillarytech/cap-ui-library/CapRadioGroup';
import { isUrl } from '../Wrapper/utils';
import { getDecodedFileName } from '../../../../utils/common';
import LineDrawer from '../Drawer';
import { CAP_SPACE_12, CAP_SPACE_08, FONT_COLOR_05, CAP_SPACE_24, CAP_SPACE_04 } from '@capillarytech/cap-ui-library/styled/variables';
import style from './style';
import { CAP_G06, CAP_G09 } from '@capillarytech/cap-ui-library/styled/variables';
import withStyles from '../../../../hoc/withStyles';

import messages from './messages';
import {
  ALLOWED_EXTENSIONS_REGEX,
  LINE_VIDEO_SIZE,
  MAX_ALLOWED_TITLE_LENGTH,
  HIDE_ACTION_BUTTON,
  DISPLAY_ACTION_BUTTON,
  MAX_ACTION_LABEL_LENGTH,
} from './constants';

export const LineVideo = ({
  className,
  id,
  intl: { formatMessage },
  isFullMode,
  inheritedTitleStyle,
  supportedExtensions,
  actions = {},
  Line,
  index,
  updateMessageState,
  content,
  activeKey,
  Templates,
  getAllTemplates,
  uploadedAssetList,
  updateUploadedAssetList,
  deleteUploadedImgList,
}) => {
  if (activeKey !== 'video') {
    return null;
  }

  const videoEl = useRef(null);

  const [errorMessageTitle, updateErrorMessageTitle] = useState(false);
  const [isCreateNew, updateCreateNew] = useState(isFullMode);
  const [messageTitle, updateTextMessageTitle] = useState('');
  const [isTemplateDrawerRequired, updateTemplateDrawerRequirement] = useState(false);
  const [selectedTemplate, updateSelectedTemplate] = useState();

  const [videoSrc, updateVideoSrc] = useState('');
  const [videoName, updateVideoName] = useState('');
  const [isVideo, updateVideoStatus] = useState(false);
  const [isVideoError, updateVideoErrorMessage] = useState(false);
  const [imagePreview, updateImagePreview] = useState();
  const [altText, updateTitle] = useState('');
  const [errorTitle, updateErrorTitle] = useState(false);
  const [selectedAction, updateSelectedAction] = useState(HIDE_ACTION_BUTTON);
  const [actionLabel, updateActionLabel] = useState('');
  const [actionLabelErrorMessage, updateActionLabelErrorMessage] = useState(false);
  const [actionUrl, updateActionUrl] = useState('');
  const [actionUrlErrorMessage, updateActionUrlErrorMessage] = useState(false);
  const [videoDuration, updateVideoDuration] = useState('');
  const [videoHeight, updateVideoHeight] = useState();
  const [videoWidth, updateVideoWidth] = useState();
  const [isPlaying, updateIsPlaying] = useState(false);


  useEffect(() => {
    const {
      messageTitle = '',
      type,
      actionLabel,
      actionUrl,
      previewImageUrl: rootPreviewImageUrl,
      video: {
        originalContentUrl = '',
        previewImageUrl = '',
        externalLink: {
          label = '',
          linkUri = '',
        } = {},
        area: {
          height,
          width,
        } = {},
      } = {},
      videoName = '',
      videoDuration = '',
      altText,
      videoSrc,
      videoHeight,
      videoWidth,
      selectedAction,
    } = content;
    const videoUrl = originalContentUrl || videoSrc;
    const videoActionLabel = label || actionLabel;
    const videoPreviewUrl = previewImageUrl || rootPreviewImageUrl;
    if (videoUrl && type === 'video') {
      updateVideoStatus(true);
      updateCreateNew(true);
      updateVideoSrc(videoUrl);
      updateTextMessageTitle(messageTitle);
      updateVideoName(videoName);
      updateVideoWidth(width || videoWidth);
      updateVideoHeight(height || videoHeight);
      updateVideoDuration(videoDuration);
      updateActionUrl(linkUri || actionUrl);
      updateActionLabel(videoActionLabel);
      updateSelectedAction(selectedAction || (videoActionLabel ? DISPLAY_ACTION_BUTTON : HIDE_ACTION_BUTTON));
      updateTitle(altText);
      if (videoPreviewUrl) {
        updateImagePreview(videoPreviewUrl);
      }
    }
  }, [content]);

  useEffect(() => {
    if (videoSrc && (isFullMode ? messageTitle : true) && imagePreview) {
      updateMessageState({
        isError: !videoSrc || !imagePreview || !altText || !checkAction() || !(isFullMode ? messageTitle : true),
        videoSrc,
        previewImageUrl: imagePreview,
        videoName,
        messageTitle,
        altText,
        index,
        type: 'video',
        actionLabel,
        actionUrl,
        videoHeight,
        videoWidth,
        videoDuration,
        selectedAction,
        messageType: 'videoSrc',
      });
    }
  }, [errorMessageTitle, videoSrc, messageTitle, isVideoError]);

  useEffect(() => {
    if (Line[`uploadedAssetDataVideo_${index}`] && Object.keys(Line[`uploadedAssetDataVideo_${index}`]).length) {
      const videoSrc = get(Line, `uploadedAssetDataVideo_${index}.metaInfo.secure_file_path`, '');
      const imgPreview = get(Line, `uploadedAssetDataVideo_${index}.metaInfo.video_file_path_preview`, '');
      const videoName = get(Line, `uploadedAssetDataVideo_${index}.metaInfo.name`, '');
      actions.clearAsset(`Video_${index}`);
      if (videoSrc) {
        updateUploadedAssetList({
          ...uploadedAssetList,
          [index]: {
            imgPreview,
            videoSrc,
            videoName,
          },
        });
      }
    }
  }, [Line[`uploadedAssetDataVideo_${index}`]]);

  useEffect(() => {
    const videoSrc = get(uploadedAssetList[index], 'videoSrc', '');
    const imgPreview = get(uploadedAssetList[index], 'imgPreview', '');
    const videoName = get(uploadedAssetList[index], 'videoName', '');
    const { type } = content;

    if (videoSrc && type === 'video') {
      updateVideoSrc(videoSrc);
      updateVideoName(videoName);
      updateVideoStatus(true);
      updateImagePreview(imgPreview);

      updateMessageState({
        isError: !videoSrc || !imagePreview || !altText || !checkAction() || !(isFullMode ? messageTitle : true),
        videoSrc,
        previewImageUrl: imagePreview,
        videoName,
        messageTitle,
        altText,
        index,
        type: 'video',
        actionLabel,
        actionUrl,
        videoHeight,
        videoWidth,
        videoDuration,
        selectedAction,
        messageType: 'videoSrc',
      });
    }
  }, [uploadedAssetList]);

  const updateMetadataLoaded = () => {
    const { current: { duration, videoHeight, videoWidth } = {} } = videoEl;
    if (duration) {
      const value = moment('1900-01-01 00:00:00').add(duration, 'seconds').format("HH.mm.ss");
      updateVideoDuration(value);
      updateVideoHeight(videoHeight);
      updateVideoWidth(videoWidth);
      updateMessageState({
        isError: !videoSrc || !imagePreview || !altText || !checkAction() || !(isFullMode ? messageTitle : true),
        videoSrc,
        previewImageUrl: imagePreview,
        videoName,
        messageTitle,
        altText,
        index,
        type: 'video',
        actionLabel,
        actionUrl,
        videoHeight,
        videoWidth,
        videoDuration: value,
        selectedAction,
        messageType: 'videoSrc',
      });
    }
  };

  const checkAction = useCallback((label = actionLabel, url = actionUrl, type = selectedAction) => type === DISPLAY_ACTION_BUTTON ? (url && label && !updateActionLabelError(label) && !updateActionUrlError(url)) : true, [actionLabel, actionUrl, selectedAction]);

  const submitVideoAction = useCallback((data, incorrectFile) => {
    const {
      file: {
        size,
      },
      file,
      fileParams,
      type,
    } = data;
    if (incorrectFile || size > LINE_VIDEO_SIZE) {
      updateVideoErrorMessage(formatMessage(messages.lineVideoIncorrectSize));
    } else {
      updateVideoErrorMessage('');
      actions.uploadAsset(
        file,
        type,
        fileParams,
        `Video_${index}`,
      );
    }
  }, []);

  const uploadVideo = useCallback((e, { files }) => {
    if (e) {
      e.preventDefault();
    }
    const _URL = window.URL || window.webkitURL;
    let incorrectFile = false;
    const file = files[0];
    if (!ALLOWED_EXTENSIONS_REGEX.test(file.name)) {
      incorrectFile = true;
    }
    const video = new FileReader();
    video.src = _URL.createObjectURL(file);
    const fileParams = {
      width: video.width,
      height: video.height,
      error: false,
      isGenerateVideoThumbnail: true,
    };
    submitVideoAction({ file, type: 'video', fileParams }, incorrectFile);
    if (e) {
      const event = e;
      event.target.value = null;
    }
  }, []);

  const capUploaderCustomVideoRequest = useCallback((uploadData) => {
    uploadVideo(undefined, { files: [uploadData.file] });
  }, []);

  const onTextTitleChange = ({ target: { value } }) => {
    updateTextMessageTitle(value);
    let errorMessage = false;
    if (value === '') {
      errorMessage = formatMessage(messages.emptyTitleErrorMessage);
    }
    updateErrorMessageTitle(errorMessage);
    updateMessageState({
      isError: !videoSrc || !imagePreview || !altText || !checkAction() || !(isFullMode ? value : true),
      videoSrc,
      previewImageUrl: imagePreview,
      videoName,
      messageTitle: value,
      altText,
      index,
      type: 'video',
      actionLabel,
      actionUrl,
      videoHeight,
      videoWidth,
      videoDuration,
      selectedAction,
      messageType: 'videoSrc',
    });
  };

  const onReUpload = () => {
    updateVideoStatus(false);
    if (!isFullMode) {
      updateCreateNew(false);
    }
    deleteUploadedImgList(index);
    updateVideoSrc('');
    updateImagePreview('');
    updateMessageState({
      isError: true,
      videoSrc: '',
      previewImageUrl: '',
      videoName: '',
      messageTitle,
      altText,
      index,
      type: 'video',
      actionLabel,
      actionUrl,
      videoHeight,
      videoWidth,
      videoDuration,
      selectedAction,
      messageType: 'videoSrc',
    });
  };

  const onSelectTemplate = useCallback((event) => {
    event.stopPropagation();
    updateTemplateDrawerRequirement(true);
  }, []);

  const playVideo = (e) => {
    if (e.target.paused && !isPlaying) {
      e.target.play();
    }
  };

  const pauseVideo = (e) => {
    if (!e.target.paused && isPlaying) {
      e.target.pause();
    }
  };

  const getVideoSection = () => {
    if (!isVideo) {
      return (
        (
          <>
            <CapHeading type="h4" style={{ marginBotton: 20, color: 'unset' }}>
              <FormattedMessage {...messages.uploadVideoLabel} />
            </CapHeading>
            <CapUploader.CapDragger
              customRequest={(data) => capUploaderCustomVideoRequest(data)}
              className="form-builder-dragger"
            >
              <CapHeading className="dragger-title" type="h7">
                <FormattedMessage {...messages.dragAndDrop} />
              </CapHeading>
              <CapHeading className="dragger-or" type="label6">
                <FormattedMessage {...messages.or} />
              </CapHeading>
              <CapButton className="dragger-button" type="secondary" style={{ marginRight: CAP_SPACE_08 }}>
                <FormattedMessage {...messages.uploadComputer} />
              </CapButton>
            </CapUploader.CapDragger>
            <CapError type="error" style={{ marginTop: CAP_SPACE_04 }}>
              {isVideoError}
            </CapError>
            <CapHeading type="h6" style={{ marginTop: CAP_SPACE_12 }} className="video-description">
              <FormattedMessage {...messages.videoFormatDescription} />
              <FormattedMessage {...messages.videoSizeDescription} />
            </CapHeading>
          </>
        )
      );
    }
    return (
      <Fragment key={videoSrc}>
        <div style={{ overflow: 'hidden' }}>
          <CapButton
            className="dragger-button"
            type="flat"
            style={{
              float: 'right',
              color: FONT_COLOR_05,
              padding: 0,
            }}
            onClick={onReUpload}
          >
            <FormattedMessage {...messages.imageReUpload} />
          </CapButton>
        </div>
        <div style={{ display: 'flex' }}>
          <video
            width="230"
            poster={imagePreview}
            className="line-image-src"
            onLoadedMetadata={() => updateMetadataLoaded()}
            onPlaying={() => updateIsPlaying(true)}
            onPause={() => updateIsPlaying(false)}
            onMouseOver={playVideo}
            onMouseOut={pauseVideo}
            ref={videoEl}
            data-testid="line-video"
          >
            <source src={videoSrc} type="video/mp4" />
          </video>
          <div style={{ marginLeft: CAP_SPACE_24 }}>
            <CapHeading type="h6">
              {getDecodedFileName(videoName)}
            </CapHeading>
            <CapHeading type="h6">
              {videoDuration}
            </CapHeading>
          </div>
        </div>
      </Fragment>
    );
  };

  const onTitleChange = ({ target: { value } }) => {
    updateTitle(value);
    let errorMessage;
    if (value === '') {
      errorMessage = formatMessage(messages.emptyAltTextErrorMessage);
    }
    updateErrorTitle(errorMessage);
    updateMessageState({
      isError: !videoSrc || !imagePreview || !value || !checkAction() || !(isFullMode ? messageTitle : true),
      videoSrc,
      previewImageUrl: imagePreview,
      videoName,
      messageTitle,
      altText: value,
      index,
      type: 'video',
      actionLabel,
      actionUrl,
      videoHeight,
      videoWidth,
      videoDuration,
      selectedAction,
      messageType: 'videoSrc',
    });
  };

  const onChangeSelectedAction = () => {
    event.stopPropagation();
    const { target: { value } } = event;
    updateSelectedAction(value);
    updateMessageState({
      isError: !videoSrc || !imagePreview || !altText || !checkAction(undefined, undefined, value) || !(isFullMode ? messageTitle : true),
      videoSrc,
      previewImageUrl: imagePreview,
      videoName,
      messageTitle,
      altText,
      index,
      type: 'video',
      actionLabel: value === HIDE_ACTION_BUTTON ? '' : actionLabel,
      actionUrl: value === HIDE_ACTION_BUTTON ? '' : actionUrl,
      videoHeight,
      videoWidth,
      videoDuration,
      selectedAction: value,
      messageType: 'videoSrc',
    });
  };

  const updateActionLabelError = (value = '') => {
    if (value.length > MAX_ACTION_LABEL_LENGTH) {
      updateActionLabelErrorMessage(formatMessage(messages.maxActionLabelErrorMessage));
      return formatMessage(messages.maxActionLabelErrorMessage);
    } else if (value === '') {
      updateActionLabelErrorMessage(formatMessage(messages.emptyLabelErrorMessage));
      return formatMessage(messages.emptyLabelErrorMessage);
    } else {
      updateActionLabelErrorMessage();
    }
  };

  const updateActionUrlError = (value) => {
    if (value === '') {
      updateActionUrlErrorMessage(formatMessage(messages.emptyUrlErrorMessage));
      return formatMessage(messages.emptyUrlErrorMessage);
    } else if (!isUrl(value)) {
      updateActionUrlErrorMessage(formatMessage(messages.inValidUrlErrorMessage));
      return formatMessage(messages.inValidUrlErrorMessage);
    } else {
      updateActionUrlErrorMessage();
    }
  };

  const onActionLabelChange = ({ target: { value } }) => {
    updateActionLabel(value);
    updateActionLabelError(value);
    updateMessageState({
      isError: !videoSrc || !imagePreview || !altText || !checkAction(value) || !(isFullMode ? messageTitle : true),
      videoSrc,
      previewImageUrl: imagePreview,
      videoName,
      messageTitle,
      altText,
      index,
      type: 'video',
      actionLabel: value,
      actionUrl,
      videoHeight,
      videoWidth,
      videoDuration,
      selectedAction,
      messageType: 'videoSrc',
    });
  };

  const onActionUrlChange = ({ target: { value } }) => {
    updateActionUrl(value);
    updateActionUrlError(value);
    updateMessageState({
      isError: !videoSrc || !imagePreview || !altText || !checkAction(undefined, value) || !(isFullMode ? messageTitle : true),
      videoSrc,
      previewImageUrl: imagePreview,
      videoName,
      messageTitle,
      altText,
      index,
      type: 'video',
      actionLabel,
      actionUrl: value,
      videoHeight,
      videoWidth,
      videoDuration,
      selectedAction,
      messageType: 'videoSrc',
    });
  };

  const getActionSection = () => (
      <>
        <CapHeading type="h6" style={{ marginTop: CAP_SPACE_12 }}>
          <FormattedMessage {...messages.actionButtonLabel} />
        </CapHeading>
        <CapRadioGroup
          name="actionButton"
          defaultValue={HIDE_ACTION_BUTTON}
          onChange={onChangeSelectedAction}
          value={selectedAction}
          options={[
            {
              label: <FormattedMessage {...messages.hide} />,
              value: HIDE_ACTION_BUTTON,
            },
            {
              label: <FormattedMessage {...messages.display} />,
              value: DISPLAY_ACTION_BUTTON,
            },
          ]}
        />
        {
          selectedAction === DISPLAY_ACTION_BUTTON
            ? (
              <>
                <CapInput
                  onChange={onActionUrlChange}
                  placeholder={formatMessage(messages.actionUrlPlaceholder)}
                  value={actionUrl}
                  errorMessage={actionUrlErrorMessage}
                  label={formatMessage(messages.actionUrlTitle)}
                  className="action-url-section"
                />
                <CapInput
                  onChange={onActionLabelChange}
                  placeholder={formatMessage(messages.actionLabelPlaceholder)}
                  value={actionLabel}
                  errorMessage={actionLabelErrorMessage}
                  label={formatMessage(messages.actionLabelTitle)}
                  inductiveText={formatMessage(messages.actionLabelInductiveTitle)}
                  addonAfter={<span>{(actionLabel || '').length} / ({MAX_ACTION_LABEL_LENGTH})</span>}
                  className="action-label-section"
                />
              </>
            )
            : null
        }
      </>
    );

  const getLineVideoSection = () => {
    if (!isCreateNew) {
      return (
        <div
          className="form-builder-dragger" style={{
            textAlign: 'center',
            border: `1px dashed ${CAP_G06}`,
            minHeight: 120,
            padding: 60,
          }}>
          <CapHeader
            className="choice-title"
            size="regular"
            title={formatMessage(messages.textMessageAddLabel)}
            style={{ marginBottom: 12 }}
          />

          <CapButton
            className="dragger-button create-button"
            type="secondary"
            style={{ marginRight: CAP_SPACE_08 }}
            onClick={setNewContent}
            isAddBtn
          >
            <FormattedMessage {...messages.textMessageCreateNew} />
          </CapButton>

          <CapHeading className="dragger-or" type="label6" style={{ display: 'inline-block' }}>
            <FormattedMessage {...messages.textMessageORLabel} />
          </CapHeading>

          <CapButton
            className="dragger-button select-template-button"
            type="secondary"
            style={{ marginLeft: CAP_SPACE_08 }}
            onClick={onSelectTemplate}
          >
            <FormattedMessage {...messages.textMessageSelectTemplate} />
          </CapButton>
        </div>
      );
    } else {
      return (
        <>
          <CapInput.TextArea
            maxLength={MAX_ALLOWED_TITLE_LENGTH}
            label={<FormattedMessage {...messages.titleLabel} />}
            inductiveText={<FormattedMessage {...messages.titleDescription} />}
            onChange={onTitleChange}
            value={altText}
            errorMessage={errorTitle}
            className="title-textarea"
          />
          {getVideoSection()}
          {getActionSection()}
        </>
      );
    }
  };

  const setNewContent = useCallback(() => updateCreateNew(true), []);

  const onTemplateSelection = (template) => {
    const {
      video: {
        originalContentUrl = '',
        previewImageUrl = '',
        externalLink: {
          label = '',
          linkUri = '',
        } = {},
        area: {
          height,
          width,
        } = {},
      } = {},
      videoName = '',
      videoDuration = '',
      altText,
    } = get(template, 'versions.base.content.messages[0]', {});

    updateSelectedTemplate(template);
    updateVideoStatus(true);
    updateTemplateDrawerRequirement(false);
    updateCreateNew(true);
    updateVideoSrc(originalContentUrl);
    updateTextMessageTitle(messageTitle);
    updateImagePreview(previewImageUrl);
    updateVideoName(videoName);
    updateVideoWidth(width);
    updateVideoHeight(height);
    updateVideoDuration(videoDuration);
    updateActionUrl(linkUri);
    updateActionLabel(label);
    updateSelectedAction(label ? DISPLAY_ACTION_BUTTON : HIDE_ACTION_BUTTON);
    updateTitle(altText);
  };

  const getLineVideoDrawerContent = () => {
    const lineTextTemplates = Templates.templates;
    if (!lineTextTemplates) {
      return null;
    }

    const cardDataList = [];
    lineTextTemplates.forEach((template) => {
      const templateData = {};
      const {
        content: {
          messages: [{
            video: {
              originalContentUrl = '',
            } = {},
          }] = [{}],
        } = {},
      } = template.versions.base;
      templateData.content = (
        <video height="279">
          <source src={originalContentUrl} type="video/mp4" />
        </video>
      );
      templateData.title = template.name;
      templateData.key = template.name;
      templateData.hoverOption = (
        <CapButton onClick={() => onTemplateSelection(template)}>
          <FormattedMessage {...messages.select} />
        </CapButton>
      );
      if (originalContentUrl) {
        cardDataList.push(templateData);
      }
    });
    return (
      <>
        <CapHeading type="h3" className="drawer-head">
          {formatMessage(messages.lineTemplateImage)}
        </CapHeading>
        <LineDrawer
          getAllTemplates={getAllTemplates}
          cardDataList={cardDataList}
          isDrawer={isTemplateDrawerRequired}
          Templates={Templates}
          searchPlaceholder={formatMessage(messages.searchImages)}
        />
      </>
    );
  };

  return (
    <div className={className}>
      {
        isFullMode
          ? (
            <CapInput
              id={`${id}_input`}
              onChange={onTextTitleChange}
              errorMessage={errorMessageTitle}
              className="image-template-title"
              style={inheritedTitleStyle || {}}
              placeholder={formatMessage(messages.textMessageTitlePlaceholder)}
              defaultValue={messageTitle || ''}
              value={messageTitle || ''}
              size="default"
              label={formatMessage(messages.textMessageTitleLabel)}
            />
          )
          : null
      }
      <form encType="multipart/form-data" id={`${id}_form`}>
        <input
          key={`${id}_videoFile`}
          style={{ display: 'none' }}
          id="fileName"
          type="file"
          onChange={(e) => uploadVideo(e, { files: e.target.files })}
          accept={supportedExtensions ? supportedExtensions : "video/*"}
        />
        {getLineVideoSection()}
        <CapDrawer
          content={getLineVideoDrawerContent()}
          visible={isTemplateDrawerRequired}
          width={624}
          onClose={() => updateTemplateDrawerRequirement(false)}
        />
      </form>
    </div>
  );
};

export default injectIntl(withStyles(LineVideo, style));
