import { generateId } from 'utils/utils';
import { api } from '../constants/config';
import http from './fetch';

const mineTypes = {
  '.css': 'text/css',
  '.csv': 'text/csv',
  '.gif': 'image/gif',
  '.htm': 'text/html',
  '.html': 'text/html',
  '.jpeg': 'image/jpeg',
  '.jpg': 'image/jpeg',
  '.js': 'text/javascript',
  '.json': 'application/json',
  '.mp3': 'audio/mpeg',
  '.png': 'image/png',
  '.svg': 'image/svg+xml',
  '.webm': 'video/webm',
  '.woff': 'font/woff',
  '.xml': 'text/xml'
};

interface ImageEventHandler extends GlobalEventHandlers {
  width: number;
  height: number;
}

interface Signature {
  expire: number;
  policy: string;
  accessid: string;
  signature: string;
  host: string;
}

export function getImageRect(img: File | string): Promise<{ width: number; height: number }> {
  return new Promise((resolve, reject) => {
    const image = new Image();
    image.src = typeof img === 'string' ? img : window.URL.createObjectURL(img);
    image.onload = function () {
      resolve({
        width: (this as ImageEventHandler).width,
        height: (this as ImageEventHandler).height
      });
    };
    image.onerror = function () {
      console.error('图片加载失败');
      reject('图片加载失败');
    };
  });
}

export function getVideoRect(video: File | string): Promise<{ width: number; height: number }> {
  return new Promise((resolve) => {
    const videoObj = document.createElement('video');
    const videoUrl = typeof video === 'string' ? video : window.URL.createObjectURL(video);
    videoObj.src = videoUrl;
    videoObj.onloadedmetadata = function () {
      window.URL.revokeObjectURL(videoUrl);
      resolve({
        width: videoObj.videoWidth,
        height: videoObj.videoHeight
      });
    };
    videoObj.load();
  });
}

export function getSignature(): Promise<Signature> {
  return new Promise((resolve, reject) => {
    http
      .get(api.signature)
      .then((res: any) => {
        resolve(res);
      })
      .catch((err) => {
        reject(err);
      });
  });
}

export async function uploadAssets({
  path,
  file,
  signal,
  rename = true,
  prefix
}: {
  path: string;
  file: File | Blob;
  signal?: AbortSignal;
  rename?: boolean;
  prefix?: string;
}) {
  // 如果文件没有type类型，根据文件后缀添加文件的type值
  if (!file.type) {
    const result = path.match(/\.[0-9a-zA-Z]+$/i);
    if (result) {
      const type = mineTypes[result[0].toLowerCase()];
      if (type) {
        file = new Blob([file], { type });
      }
    }
  }

  if (/fs/i.test(window.appConfig.UPLOAD_MODE)) {
    return uploadAssetsFs({ path, file, signal, rename, prefix });
  } else if (/oss/i.test(window.appConfig.UPLOAD_MODE)) {
    return uploadAssetsToOSS({ path, file, signal, rename, prefix });
  } else {
    return uploadAssetsToLocal({ path, file, signal, rename, prefix });
  }
}

export async function uploadAssetsToLocal({ path, file, signal, rename, prefix }) {
  if (rename) {
    path = renamePath(path, prefix);
  }

  const formData = new FormData();
  formData.append('key', path);
  formData.append('file', file);
  const result = await http.upload(api.assetsUpload, formData, { signal });

  if (result) {
    return path;
  }
}

export function uploadAssetsFs({ path, file, signal, rename, prefix }) {
  const formData = new FormData();

  if (rename) {
    path = renamePath(path, prefix);
  }
  const url = api.filesUpload + '/' + path;

  formData.append('file', file);
  return fetch(url, {
    method: 'POST',
    body: formData,
    signal
  })
    .then(() => {
      return path;
    })
    .catch((err) => {
      console.error(err);
      return;
    });
}

let signature: Signature;
export async function uploadAssetsToOSS({ path, file, signal, rename, prefix }) {
  if (!signature || !signature.expire || signature.expire < +new Date()) {
    signature = await getSignature();
  }

  if (rename) {
    path = renamePath(path, prefix);
  }
  const formData = new FormData();
  formData.append('key', path);
  formData.append('policy', signature.policy);
  formData.append('OSSAccessKeyId', signature.accessid);
  formData.append('success_action_status', '200');
  formData.append('signature', signature.signature);
  formData.append('file', file);

  return fetch(signature.host, {
    method: 'POST',
    body: formData,
    signal
  })
    .then(() => {
      return path;
    })
    .catch((err) => {
      console.error(err);
      return;
    });
}

function renamePath(path, prefix = '') {
  const pathArr = path.split('/');
  const filename = pathArr[pathArr.length - 1];
  const extname = filename.slice(filename.lastIndexOf('.'));
  pathArr[pathArr.length - 1] = prefix + generateId() + '_' + +new Date() + '_' + generateId() + extname;
  return pathArr.join('/');
}

// TODO: 将路径变为树状结构
export function getFolderTree(paths = []) {
  return paths.map((d: string) => {
    const paths = d.split('/');
    const name = paths.slice(paths.length - 1).join('/');

    return {
      name: name,
      value: d
    };
  });
}
