import { Component, ElementRef, OnInit, ViewChild, } from '@angular/core';
import * as faceapi from '@vladmandic/face-api';
import Parse from "parse"
Parse.initialize("dev");
Parse.serverURL="http://web2023.fmode.cn:9999/parse";
@Component({
  selector: 'app-results',
  templateUrl: './results.page.html',
  styleUrls: ['./results.page.scss'],
})
export class ResultsPage implements OnInit {

  @ViewChild('video', { static: true }) videoElement: ElementRef|any;
  @ViewChild('canvas', { static: true }) canvas: ElementRef|any;

//  videoWidth = 0;
//  videoHeight = 0;


  // startCamera() {
  //   if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  //     navigator.mediaDevices.getUserMedia({ video: true })
  //       .then(stream => {
  //         this.videoElement.nativeElement.srcObject = stream;
  //         this.videoElement.nativeElement.play();
  //       })
  //       .catch(err => console.error('Error accessing the camera: ', err));
  //   }
  // }

  // capture() {
  //   this.canvas.nativeElement.width = this.videoWidth;
  //   this.canvas.nativeElement.height = this.videoHeight;
  //   this.canvas.nativeElement.getContext('2d').drawImage(this.videoElement.nativeElement, 0, 0, this.videoWidth, this.videoHeight);
  //   const imgSrc = this.canvas.nativeElement.toDataURL('image/png');
  //   document.getElementById('face')?.setAttribute('src', imgSrc);

  //   setTimeout(() => {
  //       this.runFaceAnanlysis()//等待
  //   }, 2000);
  // }


  constructor() { }

 
  ngOnInit() {
    this.runFaceAnanlysis();
  }




  onFileChange(event: any) {
    const file = event.target.files[0];
    if (file) {
      const reader = new FileReader();
      reader.onload = (e: any) => {
        const img = new Image();
        img.src = e.target.result;
        img.onload = () => {
          const canvasEl = this.canvas.nativeElement;
          const context = canvasEl.getContext('2d');

          canvasEl.width = img.width;
          canvasEl.height = img.height;
          context.drawImage(img, 0, 0);

          setTimeout(() => {
            this.runFaceAnanlysis();
          }, 2000);
        };
        document.getElementById('face')?.setAttribute('src', e.target.result);
      };
      reader.readAsDataURL(file);
    }
  }


  runFaceAnanlysis(){
    console.log(faceapi);
const calculateSanTing = (positions:any) => {
  // 获取特定索引的特征点位置
  const leftEye = positions[36]; // 左眼角
  const rightEye = positions[42]; // 右眼角
  const noseBase = positions[33]; // 鼻尖
  const mouth = positions[48]; // 嘴巴中心

  // 计算三庭的比例
  const foreheadHeight = noseBase.x - leftEye.x; // 水平距离
  const noseLength = rightEye.x - leftEye.x; // 水平距离
  const chinHeight = mouth.x - noseBase.x; // 水平距离

  const foreheadHeightRounded = parseFloat(foreheadHeight.toFixed(2));
  const noseLengthRounded = parseFloat(noseLength.toFixed(2));
  const chinHeightRounded = parseFloat(chinHeight.toFixed(2));

  return {
    foreheadHeight: foreheadHeightRounded,
    noseLength: noseLengthRounded,
    chinHeight: -chinHeightRounded,
  };
};


const calculateWuYan = (positions:any) => {
  // 获取特定索引的特征点位置
  const leftEyebrow = positions[17]; // 左眉毛上角
  const rightEyebrow = positions[22]; // 右眉毛上角

  // 计算五眼的比例
  const eyeSpan = Math.abs(leftEyebrow.x - rightEyebrow.x);
  const fiveEyeSpan = eyeSpan * 5;

  const fiveEyeSpanRounded = parseFloat(fiveEyeSpan.toFixed(2));

  return fiveEyeSpanRounded;
};

const calculateFaceShape = (positions:any) => {
    // 选择关键特征点
    const jawOutline = positions.slice(0, 17); // 下巴轮廓
    const cheekLeft = positions[29]; // 左颧骨
    const cheekRight = positions[30]; // 右颧骨
    const foreheadLeft = positions[21]; // 左额头
    const foreheadRight = positions[22]; // 右额头
  
    // 计算宽度
    const cheekWidth = Math.sqrt((cheekRight.x - cheekLeft.x) ** 2 + (cheekRight.y - cheekLeft.y) ** 2);
    const foreheadWidth = Math.sqrt((foreheadRight.x - foreheadLeft.x) ** 2 + (foreheadRight.y - foreheadLeft.y) ** 2);
    const jawWidth = Math.sqrt((jawOutline[8].x - jawOutline[6].x) ** 2 + (jawOutline[8].y - jawOutline[6].y) ** 2);
  
    // 计算长度
    const faceLength = Math.sqrt((jawOutline[8].x - jawOutline[0].x) ** 2 + (jawOutline[8].y - jawOutline[0].y) ** 2);
  
    // 计算比例
    const cheekForeheadRatio = cheekWidth / foreheadWidth;
    const jawForeheadRatio = jawWidth / foreheadWidth;
    const faceAspectRatio = faceLength / foreheadWidth;
  
    // 判断脸型
    if (faceAspectRatio > 1.5) {
      // 长脸
      if (cheekForeheadRatio > 0.8 && cheekForeheadRatio < 1.2 && jawForeheadRatio < 0.8) {
        return '瓜子脸';
      } else {
        return '长形脸';
      }
    } else if (faceAspectRatio < 1) {
      // 宽脸
      return '宽脸';
    } else {
      // 标准脸
      if (cheekForeheadRatio > 0.8 && cheekForeheadRatio < 1.2 && jawForeheadRatio > 0.8) {
        return '心形脸';
      } else if (cheekForeheadRatio < 0.8 && jawForeheadRatio < 0.8) {
        return '菱形脸';
      } else {
        return '标准脸';
      }
    }
  };

// 封装计算眉形的函数
const calculateBrowShape = (positions:any) => {
    // 选择关键特征点
    const leftEyebrowLeft = positions[17]; // 左眉毛上角
    const leftEyebrowRight = positions[22]; // 左眉毛下角
    const rightEyebrowLeft = positions[25]; // 右眉毛上角
    const rightEyebrowRight = positions[31]; // 右眉毛下角
  
    // 计算眉毛宽度
    const leftBrowWidth = Math.abs(leftEyebrowLeft.x - leftEyebrowRight.x);
    const rightBrowWidth = Math.abs(rightEyebrowLeft.x - rightEyebrowRight.x);
    const browWidth = Math.max(leftBrowWidth, rightBrowWidth);
  
    // 计算眉毛长度
    const leftBrowLength = Math.sqrt((leftEyebrowLeft.x - leftEyebrowRight.x) ** 2 + (leftEyebrowLeft.y - leftEyebrowRight.y) ** 2);
    const rightBrowLength = Math.sqrt((rightEyebrowLeft.x - rightEyebrowRight.x) ** 2 + (rightEyebrowLeft.y - rightEyebrowRight.y) ** 2);
    const browLength = Math.max(leftBrowLength, rightBrowLength);
  
    // 判断眉形
    if (browWidth > 0.5 * browLength) {
      return '浓眉';
    } else if (browWidth < 0.3 * browLength) {
      return '细眉';
    } else {
      return '标准眉';
    }
  
    // 其他眉形判断条件可以添加在这里
    // ...
  };

  // 封装计算唇形的函数
const calculateLipShape = (positions:any) => {
    // 选择关键特征点
    const upperLipTop = positions[61]; // 上嘴唇顶部
    const upperLipBottom = positions[62]; // 上嘴唇底部
    const lowerLipTop = positions[63]; // 下嘴唇顶部
    const lowerLipBottom = positions[64]; // 下嘴唇底部
  
    // 判断唇形
    if (upperLipBottom.y - upperLipTop.y > 10 && lowerLipBottom.y - lowerLipTop.y > 10) {
      return '厚唇';
    } else if (upperLipBottom.y - upperLipTop.y < 5 && lowerLipBottom.y - lowerLipTop.y < 5) {
      return '薄唇';
    } else if (upperLipBottom.y - upperLipTop.y > 10 && lowerLipBottom.y - lowerLipTop.y < 5) {
      return '微笑唇';
    } else if (upperLipBottom.y - upperLipTop.y < 5 && lowerLipBottom.y - lowerLipTop.y > 10) {
      return '嘟嘟唇';
    } else {
      return '标准唇型';
    }
  };
  // 封装计算眼睛形状的函数
const calculateEyeShape = (positions:any) => {
    // 选择关键特征点
    const leftEyeInner = positions[33]; // 左眼内侧
    const leftEyeOuter = positions[39]; // 左眼外侧
    const rightEyeInner = positions[45]; // 右眼内侧
    const rightEyeOuter = positions[51]; // 右眼外侧
  
    // 计算眼睛长度
    const leftEyeLength = Math.sqrt((leftEyeInner.x - leftEyeOuter.x) ** 2 + (leftEyeInner.y - leftEyeOuter.y) ** 2);
    const rightEyeLength = Math.sqrt((rightEyeInner.x - rightEyeOuter.x) ** 2 + (rightEyeInner.y - rightEyeOuter.y) ** 2);
    const eyeLength = Math.max(leftEyeLength, rightEyeLength);
  
    // 判断眼睛形状
    if (eyeLength > 10 && leftEyeLength > rightEyeLength) {
      return '杏仁眼';
    } else if (eyeLength > 10 && leftEyeLength < rightEyeLength) {
      return '圆形眼';
    } else if (leftEyeInner.y > leftEyeOuter.y) {
      return '单眼皮';
    } else {
      return '双眼皮';
    }
  };
  
  // 封装计算鼻形的函数
  const calculateNoseShape = (positions:any) => {
    // 选择关键特征点
    const noseBase = positions[33]; // 鼻尖
    const noseTip = positions[34]; // 鼻尖
    const noseSide = positions[35]; // 鼻翼
  
    // 判断鼻形
    if (noseBase.y > noseTip.y && noseSide.x > noseTip.x) {
      return '鹰钩鼻';
    } else if (noseBase.y > noseTip.y && noseSide.x < noseTip.x) {
      return '蒜头鼻';
    } else if (noseBase.y < noseTip.y) {
      return '直鼻';
    } else {
      return '塌鼻';
    }
  };
  
  // 封装计算颧骨的函数
  const calculateCheekBones = (positions:any) => {
    // 选择关键特征点
    const cheekLeft = positions[29]; // 左颧骨
    const cheekRight = positions[30]; // 右颧骨
  
    // 判断颧骨
    if (cheekLeft.y > cheekRight.y) {
      return '颧骨高';
    } else {
      return '颧骨平';
    }
  };
  
  // 封装计算下巴的函数
  const calculateChin = (positions:any) => {
    // 选择关键特征点
    const chin = positions[60]; // 下巴中心
  
    // 判断下巴
    if (chin.y < chin.x) {
      return '长下巴';
    } else if (chin.y > chin.x) {
      return '短下巴';
    } else {
      return '尖下巴';
    }
  };
  
  // 封装计算额头的函数
  const calculateForehead = (positions:any) => {
    // 选择关键特征点
    const foreheadLeft = positions[21]; // 左额头
    const foreheadRight = positions[22]; // 右额头
  
    // 判断额头
    if (foreheadLeft.x > foreheadRight.x) {
      return '宽额头';
    } else {
      return '窄额头';
    }
  };
  

  const calculateCheeksShape = (positions:any) => {
    // 选择关键特征点
    const cheekLeft = positions[29]; // 左颧骨
    const cheekRight = positions[30]; // 右颧骨
  
    // 判断脸颊形状
    if (cheekLeft.y > cheekRight.y) {
      return '丰满脸颊';
    } else {
      return '瘦削脸颊';
    }
  };

  

  
const run = async () => {
  // 加载模型
  await Promise.all([
    faceapi.nets.ssdMobilenetv1.loadFromUri('/assets/models'),
    faceapi.nets.faceLandmark68Net.loadFromUri('/assets/models'),
    faceapi.nets.faceRecognitionNet.loadFromUri('/assets/models'),
    faceapi.nets.ageGenderNet.loadFromUri('/assets/models'),
  ]);

  const face1:any = document.getElementById('face');

  let faceAIData = await faceapi
    .detectAllFaces(face1)
    .withFaceLandmarks()
    .withFaceDescriptors()
    .withAgeAndGender();

  console.log(faceAIData);

  // 获取第一个检测到的人脸的特征点
  const landmarks:any = faceAIData[0].landmarks;
  const positions:any = landmarks._positions;

  // 计算三庭和五眼的比例
  const sanTing = calculateSanTing(positions);//计算三庭
  const wuYan = calculateWuYan(positions);//计算五眼
  // 计算脸型
  const faceShape = calculateFaceShape(positions);
  // 计算眉形
  const browShape = calculateBrowShape(positions);
  // 计算唇形
  const lipShape = calculateLipShape(positions);
  // 计算眼睛形状
  const eyeShape = calculateEyeShape(positions);
  // 计算鼻形
  const noseShape = calculateNoseShape(positions);
  // 计算颧骨
  const cheekBones = calculateCheekBones(positions);
  // 计算下巴
  const chinShape = calculateChin(positions);
  // 计算额头
  const foreheadShape = calculateForehead(positions);
  // 计算脸颊
  const cheeksShape = calculateCheeksShape(positions);

 console.log(`三庭比例: ${sanTing.foreheadHeight},${sanTing.noseLength}, ${sanTing.chinHeight}`);
 console.log(`五眼比例: ${wuYan}`);
 console.log(`脸型: ${faceShape}`);
 console.log(`眉形: ${browShape}`);
 console.log(`唇形: ${lipShape}`);
 console.log(`眼睛形状: ${eyeShape}`);
 console.log(`鼻形: ${noseShape}`);
 console.log(`颧骨: ${cheekBones}`);
 console.log(`下巴: ${chinShape}`);
 console.log(`额头: ${foreheadShape}`);
 console.log(`脸颊: ${cheeksShape}`);

 const sanTingElement = document.getElementById('sanTing');
 const wuYanElement = document.getElementById('wuYan');
 const faceShapeElement = document.getElementById('faceShape');
 const browShapeElement = document.getElementById('browShape');
 const lipShapeElement = document.getElementById('lipShape');
 const eyeShapeElement = document.getElementById('eyeShape');
 const noseShapeElement = document.getElementById('noseShape');
 const cheekBonesElement = document.getElementById('cheekBones');
 const chinShapeElement = document.getElementById('chinShape');
 const foreheadShapeElement = document.getElementById('foreheadShape');
 const cheeksShapeElement = document.getElementById('cheeksShape');

 if (sanTingElement) sanTingElement.textContent = `${sanTing.foreheadHeight}, ${sanTing.noseLength}, ${sanTing.chinHeight}`;
 if (wuYanElement) wuYanElement.textContent = `${wuYan}`;
 if (faceShapeElement) faceShapeElement.textContent = faceShape;
 if (browShapeElement) browShapeElement.textContent = browShape;
 if (lipShapeElement) lipShapeElement.textContent = lipShape;
 if (eyeShapeElement) eyeShapeElement.textContent = eyeShape;
 if (noseShapeElement) noseShapeElement.textContent = noseShape;
 if (cheekBonesElement) cheekBonesElement.textContent = cheekBones;
 if (chinShapeElement) chinShapeElement.textContent = chinShape;
 if (foreheadShapeElement) foreheadShapeElement.textContent = foreheadShape;
 if (cheeksShapeElement) cheeksShapeElement.textContent = cheeksShape;
};
run();
  }

}
