/*
 * Copyright (C) 2024 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 { PixelMapTransformation } from './PixelMapTransformation';
import { Size } from '@kit.ArkUI';
import { image } from '@kit.ImageKit';

/**
 * 图片变换:圆形裁剪效果
 */
@Sendable
export class CropCircleTransformation extends PixelMapTransformation {
  private mCenterX: number = 0;
  private mCenterY: number = 0;
  private mRadius: number = 0;

  constructor() {
    super();
  }

  getName(): string {
    return this.constructor.name + ';mCenterX:' + this.mCenterX + ';mCenterY:' + this.mCenterY + ';mRadius:' + this.mRadius;
  }

  async transform(context: Context, toTransform: PixelMap, width: number, height: number): Promise<PixelMap> {
    return await this.transformCircle(toTransform);
  }

  private async transformCircle(data: PixelMap): Promise<PixelMap> {
    let imageInfo: image.ImageInfo = await data.getImageInfo();
    let size: Size = {
      width: imageInfo.size.width,
      height: imageInfo.size.height
    };
    if (!size) {
      console.error('CropCircleTransformation The image size does not exist.');
      return data;
    }
    let height: number = size.height;
    let width: number = size.width;
    this.mRadius = 0;
    if (width > height) {
      this.mRadius = height / 2;
    } else {
      this.mRadius = width / 2;
    }
    this.mCenterX = width / 2;
    this.mCenterY = height / 2;

    let bufferData: ArrayBuffer = new ArrayBuffer(data.getPixelBytesNumber());
    await data.readPixelsToBuffer(bufferData);

    let dataArray = new Uint8Array(bufferData);

    for (let h = 0; h <= height; h++) {
      for (let w = 0; w <= width; w++) {
        if (this.isContainsCircle(w, h)) {
          continue;
        }
        // 针对的点
        let index = (h * width + w) * 4;
        dataArray[index] = 0;
        dataArray[index+1] = 0;
        dataArray[index+2] = 0;
        dataArray[index+3] = 0;
      }
    }
    await data.writeBufferToPixels(bufferData);
    return data;
  }

  isContainsCircle(x: number, y: number): boolean {
    let a = Math.pow((this.mCenterX - x), 2);
    let b = Math.pow((this.mCenterY - y), 2);
    let c = Math.sqrt((a + b));
    return c <= this.mRadius;
  }
}