import * as React from 'react';
import classNames from 'classnames/bind';
import TextItem from 'components/items/TextItem';

import CKEditor from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import { getFileName } from 'store/utils/api';

import FormElement from 'components/structure/FormElement';
import FieldWrapper from 'components/structure/FieldWrapper';

import Cropper from 'components/global/Cropper';

import CustomIcon from 'components/items/CustomIcon';
import { FaExpandAlt } from 'react-icons/fa';
import CodeEditorInput from 'components/formItems/CodeEditorInput';
import styleIdentifiers from './ckEditorField.scss';
import UploadAdapter from './UploadAdapter';

const styles = classNames.bind(styleIdentifiers);

type CkEditorFieldProps = FormElementProps &
  FieldWrapperProps &
  FormItemLabelProps & {
    name: string;
    placeholder?: string;
    dialogShow: Function;
    dialogHide: Function;
    aspectRatio?: number;
    upload: Function;
    uploadUrl: string;
    noResize?: boolean;
  };

interface CkEditorFieldState {
  code: boolean;
}

export default class CkEditorField extends React.Component<CkEditorFieldProps, CkEditorFieldState> {
  constructor(props: CkEditorFieldProps) {
    super(props);
    this.state = {
      code: false,
    };
  }

  // Add a custom adapter
  myAdapter = (editor: any) => {
    const { dialogHide } = this.props;

    editor.plugins.get('FileRepository').createUploadAdapter = loader =>
      // Attach a custom upload adapter and provide the loader
      new UploadAdapter({
        loader,
        onFileSelected: this.onFileSelected,
        cancel: () => dialogHide('custom'),
      });
  };

  onFileSelected = (file: File, callback: Function, progressFunc?: Function) => {
    const self = this;

    const { noResize } = this.props;

    if (noResize) {
      this.uploadImage(file, callback, progressFunc);
      return;
    }
    // read file
    const reader = new FileReader();

    reader.onload = () => {
      const fileAsBinaryString = reader.result;

      self.resizeImage(fileAsBinaryString, callback, progressFunc);
    };

    reader.onabort = () => {
      callback({
        error: true,
        message: 'file reading was aborted',
      });
    };
    reader.onerror = () => {
      callback({
        error: true,
        message: 'file reading has failed',
      });
    };
    reader.readAsDataURL(file);
  };

  // Use cropper to resize
  resizeImage = (binary: string, callback: Function, progressFunc?: Function) => {
    const { dialogShow, aspectRatio, apollo } = this.props;
    // return;
    dialogShow({
      id: 'custom',
      medium: true,
      noBackgroundClose: true,
      closeButton: 'light',
      closePosition: 'right',
      children: (
        <Cropper
          aspectRatio={aspectRatio}
          apollo={apollo}
          src={binary}
          action={file => this.uploadImage(file, callback, progressFunc)}
        />
      ),
    });
  };

  uploadImage = (file: File, callback: Function, progressFunc?: Function) => {
    const { dialogHide, upload, uploadUrl, apollo, uploadPrefix } = this.props;

    if (apollo && upload) {
      upload({
        data: {
          title: getFileName(uploadPrefix, file, false),
          base64: file,
        },
        callback,
      });
    } else if (!apollo) {
      if (uploadUrl && upload) {
        upload({
          url: uploadUrl,
          file,
          fileName: getFileName(uploadPrefix, file, false),
          callback,
          noLoading: true,
          callbackError: errorData => {
            callback({
              ...errorData,
              error: true,
              message: 'upload failed, server issue',
            });
          },
          progress: data => {
            if (progressFunc) progressFunc(data);
          },
        });
      } else {
        callback({
          error: true,
          message: 'no upload data provided',
        });
      }
    }

    dialogHide('custom');
  };

  handleChange = (event: KeyboardEvent, editor: Record<string, any>) => {
    const { input } = this.props;

    const data = editor.getData();

    if (input) input.onChange(data);
  };

  switchType = () => {
    const { code } = this.state;

    this.setState({
      code: !code,
    });
  };

  renderInput = () => {
    const { code } = this.state;
    const { input, disabled } = this.props;
    return !code ? (
      <CKEditor
        editor={ClassicEditor}
        config={{
          extraPlugins: [this.myAdapter],
        }}
        data={input && input.value}
        onInit={editor => {
          this.editor = editor;
        }}
        disabled={disabled}
        onChange={this.handleChange}
      />
    ) : (
      <div className={styles('code-input-wrapper')}>
        <CodeEditorInput
          disabled={disabled}
          name={name}
          {...this.props}
          label=""
          className={styles('code-input')}
          noMargin
          language="jsx"
        />
      </div>
    );
  };

  openFullScreen = () => {
    const { dialogShow } = this.props;

    dialogShow({
      id: 'wysiwyg',
      style: { zIndex: 10 },
      large: true,
      children: <div className={styles('cke-modal')}>{this.renderInput()}</div>,
    });
  };

  /* insertImage = () => {
    if (!this.editor) return;
    console.log(this.editor);
     this.editor.execute('insertImage', {
      src:
        'https://s3.eu-central-1.amazonaws.com/tipaw-pictures/f851775c-314b-449f-ac26-ce4dd6d93b89.jpg',
    }); 
    const { input } = this.props;

    let data = this.editor.getData();

    data +=
      "<img src='https://s3.eu-central-1.amazonaws.com/tipaw-pictures/f851775c-314b-449f-ac26-ce4dd6d93b89.jpg'/>";
    input.onChange(data);
  }; */

  render() {
    const { className, input, valueClassName, disabled, name, effect, placeholder } = this.props;
    const { code } = this.state;
    return (
      <FormElement {...this.props} className={styles('CkEditorField', className)}>
        <FieldWrapper
          {...this.props}
          valueClassName={styles('editor-wrapper', code && 'code-wrapper', valueClassName)}
        >
          <div className={styles('top-actions', code && 'code')}>
            <div className={styles('switch')} onClick={this.switchType}>
              <TextItem path={!code ? 'Switch to code' : 'Go back to editor'} />
            </div>
            {!code && (
              <div className={styles('open-full')} onClick={this.openFullScreen}>
                <FaExpandAlt />
              </div>
            )}
          </div>
          {this.renderInput()}
        </FieldWrapper>
      </FormElement>
    );
  }
}
