import { Injectable } from '@angular/core';

// @ts-ignore
import ObsClient from "esdk-obs-browserjs"

import Parse from "parse";

/**
 * HwobsDir 华为OBS目录接口
 * @public
 */
export interface HwobsDir{
  Prefix:string  // "storage/2023/"

}

/**
 * HwobsDir 华为OBS文件接口
 * @public
 */
export interface HwobsFile{
  ETag: "\"f0ec968fe51ab48348307e06476122eb\""
  Key:string  //"storage/3mkf41033623275.png"
  LastModified:string //"2023-11-08T12:03:13.008Z"
  Owner:object // {ID: '09971a1979800fb60fbbc00ada51f7e0'}
  Size:string //"25839"
  StorageClass:string //"STANDARD"
}

/**
 * HwobsProvider 华为OBS文件服务
 * @public
 */
export class HwobsProvider {
  obsClient:ObsClient
  bucketName:string
  host:string
  globalPrefix:string = ""
  constructor(options:{
    host:string
    bucketName:string
    access_key_id:string
    secret_access_key:string
    prefix?:string
    server?:string
  }) {
      this.globalPrefix = options.prefix || ""
      this.host = options?.host
      this.bucketName = options?.bucketName
      this.obsClient = new ObsClient({
        access_key_id: options.access_key_id,       
        secret_access_key: options.secret_access_key,
        // 这里以华南-广州为例，其他地区请按实际情况填写
        server: options?.server||'https://obs.cn-south-1.myhuaweicloud.com'
    });
  }

  /**
   * 目录及检索相关函数
   */
  listDir(prefix:any):Promise<{
    dirs:Array<HwobsDir>,
    files:Array<HwobsFile>
  }>{
    return new Promise((resolve,reject)=>{
        this.obsClient.listObjects({
          Bucket : this.bucketName,
          Prefix : prefix,
          Delimiter: '/'
        }, (err:any, result:any) => {
          if(err){              
            console.error('Error-->' + err);   
            reject(err)    
          }else{              
            console.log('Status-->' + result.CommonMsg.Status);
            console.log(result)
                    if(result.CommonMsg.Status < 300 && result.InterfaceResult){
                          for(var j in result.InterfaceResult.Contents){
                                    console.log('Contents[' + j +  ']:');
                                    console.log('Key-->' + result.InterfaceResult.Contents[j]['Key']);
                                    console.log('Owner[ID]-->' + result.InterfaceResult.Contents[j]['Owner']['ID']);
                            }
                    }       
                    let dirs:HwobsDir[] = result.InterfaceResult.CommonPrefixes
                    let files:HwobsFile[] = result.InterfaceResult.Contents
                    resolve({dirs:dirs,files:files})     
          }
        });
      })

  }

  /**
   * 文件上传相关函数
   * @param file 
   * @param key 
   * @returns 
   */
  async uploadFile(file:File,key:string):Promise<Parse.Object>{
    console.log(this.globalPrefix,key)
    // key 文件上传后的全部路径
    // /storage/<公司账套>/<应用名称>/年月日/<文件名>.<文件后缀>
    // /storage/web2023/<学号>/年月日/<文件名>.<文件后缀>
    let attach = await this.checkFileExists(file);
    if(attach?.id) return attach
      return new Promise((resolve,reject)=>{
        this.obsClient.putObject({
              Bucket : this.bucketName,
              Key : this.globalPrefix+key,
              SourceFile : file
        },  async (err:any, result:any) => {
              if(err){
                    console.error('Error-->' + err);
                    reject(err)
              }else{
                console.log('Status-->' + result.CommonMsg.Status);
                let attach = await this.saveAttachment(file,this.globalPrefix+key)
                resolve(attach)
              }
        });
      })
  }
  Attachment = Parse.Object.extend("Attachment")

  async checkFileExists(file:any):Promise<Parse.Object>{
    let hash = await this.getFileHash(file)
    // 文件HASH查重,避免重复上传
    let attach:Parse.Object
    let query = new Parse.Query("Attachment")
    query.equalTo("hash",hash);
    query.equalTo("size",file.size);
    let exists:any = await query.first();
    if(!exists?.id) exists = new this.Attachment()
    attach = exists
    return attach
  }
  async saveAttachment(file:File,key:string){
    console.log("saveAttachment",key)
    let hash = await this.getFileHash(file)
    let attach = await this.checkFileExists(file)
    attach.set("name",file.name)
    attach.set("size",file.size)
    attach.set("mime",file.type)
    attach.set("url",this.host + key)
    attach.set("hash",hash)
    attach = await attach.save()
    return attach
  }

  async getFileHash(file:File) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = async (event:any) => {
        const buffer = event.target.result;
        const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
        const hashArray = Array.from(new Uint8Array(hashBuffer));
        const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('');
        resolve(hashHex);
      };
      reader.onerror = (event:any) => {
        reject(event.target.error);
      };
      reader.readAsArrayBuffer(file);
    });
  }
}
