/*
 * Copyright (c) 2026 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { fileIo, fileUri } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';
import { commonType } from '@kit.ArkData';
import { image } from '@kit.ImageKit';
import { MediaInfo, MediaType } from '../model/ContentInfo';

const DOMAIN = 0x0000;
const TAG = 'FileUtil';
const FORMAT = '%{public}s';

/*
 * Select a picture from the gallery.
 * @returns uri The uri for the selected file.
 */
export async function fileSelect(): Promise<Array<string>> {
  let imgUri: Array<string> = [];
  let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
  photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
  photoSelectOptions.maxSelectNumber = 5;
  let photoPicker = new photoAccessHelper.PhotoViewPicker();
  try {
    let photoSelectResult = await photoPicker.select(photoSelectOptions);
    if (photoSelectResult && photoSelectResult.photoUris && photoSelectResult.photoUris.length > 0) {
      imgUri = photoSelectResult.photoUris;
      return imgUri;
    } else {
      return [];
    }
  } catch (error) {
    hilog.error(DOMAIN, TAG, FORMAT, `PhotoViewPicker failed with err: ${error.code}, ${error.message}`);
    return [];
  }
}

// [Start write]
// [Start write_distributed_file]
export function writeDistributedFile(context: common.UIAbilityContext, displayName: string, mediaType: MediaType,
  buf?: ArrayBuffer, uri?: string): void {
  // The asset is written to the distributed file directory.
  // Obtain the distributed file directory path.
  let distributedDir: string = context.distributedFilesDir;
  let fileName: string = '/' + displayName;
  let filePath: string = distributedDir + fileName;
  let file: fileIo.File | undefined = undefined;
  let srcFile: fileIo.File | undefined = undefined;
  try {
    // Create a file in a distributed directory.
    file = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
    hilog.info(DOMAIN, TAG, FORMAT, 'Create file success.');
    if (mediaType === MediaType.MEDIA_IMAGE && buf) {
      // Write content to a file (if the asset is a picture, the picture can be converted to a buffer to write)
      fileIo.writeSync(file.fd, buf);
    } else if (mediaType === MediaType.MEDIA_VIDEO && uri) {
      srcFile = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY);
      fileIo.copyFileSync(srcFile.fd, file.fd);
    }
  } catch (error) {
    let err: BusinessError = error as BusinessError;
    hilog.info(DOMAIN, TAG, FORMAT,
      `Failed to openSync / writeSync / closeSync. Code: ${err.code}, message: ${err.message}`);
  } finally {
    // closed file.
    if (file) {
      fileIo.closeSync(file.fd);
    }
    if (srcFile) {
      fileIo.closeSync(srcFile.fd);
    }
  }
}

// [End write]
// [End write_distributed_file]

// [Start fileCopy]
// [Start file_copy]
/*
 * Copy distributed files.
 * @param attachmentRecord
 * @param key
 */
export function fileCopy(context: common.UIAbilityContext, attachment: commonType.Asset,
  mediaUriArray: Array<MediaInfo>): void {
  if (canIUse('SystemCapability.DistributedDataManager.CommonType')) {
    let mediaName = attachment.name.substring(attachment.name.indexOf('_') + 1);
    let mediaType = attachment.name.substring(0, attachment.name.indexOf('_'));
    let filePath: string = context.distributedFilesDir + '/' + mediaName;
    let savePath: string = context.filesDir + '/' + mediaName;
    let file: fileIo.File | undefined = undefined;
    let saveFile: fileIo.File | undefined = undefined;
    let imageSourceApi: image.ImageSource | undefined;
    try {
      if (fileIo.accessSync(filePath)) {
        saveFile = fileIo.openSync(savePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
        file = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE);
        let buf: ArrayBuffer = new ArrayBuffer(Number(attachment.size));
        let readSize = 0;
        let readLen = fileIo.readSync(file.fd, buf, {
          offset: readSize
        });
        if (mediaType == MediaType.MEDIA_IMAGE) {
          let sourceOptions: image.SourceOptions = {
            sourceDensity: 120
          };
          imageSourceApi = image.createImageSource(buf, sourceOptions);
          mediaUriArray.push({
            imagePixelMap: imageSourceApi.createPixelMapSync(),
            mediaName: mediaName,
            mediaType: mediaType
          });
        } else if (mediaType == MediaType.MEDIA_VIDEO) {
          mediaUriArray.push({
            videoUri: attachment.uri,
            mediaName: mediaName,
            mediaType: mediaType
          })
        }

        while (readLen > 0) {
          readSize += readLen;
          fileIo.writeSync(saveFile.fd, buf);
          readLen = fileIo.readSync(file.fd, buf, {
            offset: readSize
          });
        }
        hilog.info(DOMAIN, TAG, FORMAT, `${attachment.name} synchronized successfully.`);
      }
    } catch (error) {
      let err: BusinessError = error as BusinessError;
      hilog.error(DOMAIN, TAG, FORMAT, `${attachment.name} fileCopy failed with err: ${JSON.stringify(err)}`);
    } finally {
      if (file) {
        fileIo.closeSync(file.fd);
      }
      if (saveFile) {
        fileIo.closeSync(saveFile.fd);
      }
      if (imageSourceApi) {
        imageSourceApi.release();
        imageSourceApi = undefined;
      }
    }
  }
}

// [End fileCopy]
// [End file_copy]
/*
 * Obtain distributed file asset information.
 * @param append
 * @returns
 */
export function getAssetInfo(context: common.UIAbilityContext, append: MediaInfo): commonType.Asset {
  let filePath = context.distributedFilesDir + '/' + append.mediaName;
  let attachment: commonType.Asset;
  try {
    fileIo.statSync(filePath);
    let uri: string = fileUri.getUriFromPath(filePath);
    let stat = fileIo.statSync(filePath);
    attachment = {
      name: `${append.mediaType}_${append.mediaName}`,
      uri: uri,
      path: filePath,
      createTime: stat.ctime.toString(),
      modifyTime: stat.ctime.toString(),
      size: stat.size.toString()
    };
    hilog.info(DOMAIN, TAG, FORMAT, `[getAssetInfo] attachments: ${JSON.stringify(attachment)}`);
  } catch (err) {
    hilog.error(DOMAIN, TAG, FORMAT, `StatSync failed. Cause code: ${err.code}, message: ${err.message}`);
  }
  return attachment!;
}