package com.yonge.netty.server.service;

import io.netty.channel.Channel;

import java.util.HashMap;
import java.util.Map;

import javax.sound.sampled.AudioFormat;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.yonge.audio.analysis.AudioFloatConverter;
import com.yonge.audio.analysis.detector.YINPitchDetector;
import com.yonge.netty.dto.WebSocketResponse;
import com.yonge.netty.server.handler.NettyChannelManager;
import com.yonge.netty.server.handler.message.MessageHandler;

@Component
public class PitchDetectionHandler implements MessageHandler {
	
	private final static Logger LOGGER = LoggerFactory.getLogger(PitchDetectionHandler.class);

	/**
	 * @describe 采样率
	 */
	private float sampleRate = 44100;

	/**
	 * 每个采样大小（Bit）
	 */
	private int bitsPerSample = 16;

	/**
	 * 通道数
	 */
	private int channels = 1;
	
	private boolean signed = true;

	private boolean bigEndian = false;

	private AudioFormat audioFormat = new AudioFormat(sampleRate, bitsPerSample, channels, signed, bigEndian);

	private AudioFloatConverter converter = AudioFloatConverter.getConverter(audioFormat);
	
	@Autowired
	private NettyChannelManager nettyChannelManager;
	
	@Override
	public String getAction() {
		return "PITCH_DETECTION";
	}

	@Override
	public boolean handleTextMessage(String user, Channel channel, String text) {

		return true;
	}

	@Override
	public boolean handleBinaryMessage(String userId, Channel channel, byte[] bytes) {

		float[] samples = new float[bytes.length / 2];

		if (samples.length == 0) {
			return false;
		}

		converter.toFloatArray(bytes, samples);

		YINPitchDetector frequencyDetector = new YINPitchDetector(samples.length, audioFormat.getSampleRate());

		int playFrequency = (int) frequencyDetector.getFrequency(samples);
		
		LOGGER.info("校音频率：{}", playFrequency);

		Map<String, Object> params = new HashMap<String, Object>();
		params.put("frequency", playFrequency);

		WebSocketResponse<Map<String, Object>> resp = new WebSocketResponse<Map<String, Object>>("checking", params);

		nettyChannelManager.sendTextMessage(userId, resp);

		return true;
	}
	
}
