package com.its.pis.xnettcp.vds.process;

import com.its.app.utils.ItsUtils;
import com.its.app.utils.NettyUtils;
import com.its.app.utils.SysUtils;
import com.its.pis.entity.TbVdsCtlr;
import com.its.pis.xnettcp.center.protocol.CenterResProtocol;
import com.its.pis.xnettcp.vds.protocol.VdsProtocol;
import com.its.pis.xnettcp.vds.protocol.VdsReqImage;
import com.its.pis.xnettcp.vds.protocol.VdsResFramePacket;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;
import java.util.List;

@Slf4j
@RequiredArgsConstructor
public class Job_Image implements JobProtocol {

	private final VdsResFramePacket packet;

	@Override
	public int parse() {
		// 정지영상 데이터 수신
		if (this.packet == null || this.packet.getVdsObj() == null) {
			log.error("Job_Image, packet or object data null");
			return 0;
		}

		TbVdsCtlr obj = this.packet.getVdsObj();
		byte[] body = this.packet.getBody();
		if (body == null || body.length < 6) {
			log.error("[{}]. Job_Image: Data Body Length Error, {}", this.packet.getObjectInfo(), (body == null) ? 0 : body.length);
			return 0;
		}

		ByteBuffer byteBuffer = ByteBuffer.wrap(body);
		byteBuffer.order(VdsProtocol.byteOrder);

		int pktSize = byteBuffer.array().length;
		int total = byteBuffer.getShort();
		int current = byteBuffer.getShort();
		int dataLen = byteBuffer.getShort();

		log.info("[{}]. Job_Image: image data receive: total {}, current {}, dataLen {}, pktSize {}", obj.getVDS_CTLR_ID(), total, current, dataLen, pktSize);

		if (dataLen > 6) {
			int imageSize = dataLen - 6;
			byte[] imageData = new byte[imageSize];
			byteBuffer.get(imageData);
			obj.addImageSize(imageSize);
			obj.addImageData(imageData);
			log.info("[{}]. Job_Image: image data save: currentSize {}, totalSize {}", obj.getVDS_CTLR_ID(), imageSize, obj.getImageData().array().length);
		}
		else {
			log.error("[{}]. Job_Image: image data receive size error: total {}, current {}, dataLen {}", obj.getVDS_CTLR_ID(), total, current, dataLen);
			obj.setStopImageResponse();
			return 0;
		}

		int nextFrame = current+1;
		if (total == nextFrame) {
			log.info("[{}]. Job_Image: completed image data receive: {}", obj.getVDS_CTLR_ID(), obj.getImageSize());
			List<Channel> channels = obj.getRequestImageList();
			ByteBuffer buffer1 = CenterResProtocol.getImageHeader1();
			ByteBuffer buffer2 = CenterResProtocol.getImageHeader2(obj.getImageSize());
			ByteBuffer buffer3 = obj.getImageData();
			channels.forEach(channel -> {
				if (channel == obj.getChannel()) {
					// 서버 화면에서 요청한 거임
				}
				else {
					if (sendCenterResponse(channel, buffer1, obj)) {
						log.info("[{}]. Job_Image: send image data to center[HEAD1]: {} Bytes. {}", obj.getVDS_CTLR_ID(), buffer1.array().length, NettyUtils.getRemoteAddress(channel));
					}
				}
			});
			channels.forEach(channel -> {
				if (channel == obj.getChannel()) {
					// 서버 화면에서 요청한 거임
				}
				else {
					if (sendCenterResponse(channel, buffer2, obj)) {
						log.info("[{}]. Job_Image: send image data to center[HEAD2]: {} Bytes. {}", obj.getVDS_CTLR_ID(), buffer2.array().length, NettyUtils.getRemoteAddress(channel));
					}
				}
			});
			channels.forEach(channel -> {
				if (channel == obj.getChannel()) {
					// 서버 화면에서 요청한 거임
					log.error("YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY");
				}
				else {
					if (sendCenterResponse(channel, buffer3, obj)) {
						log.info("[{}]. Job_Image: send image data to center[DATA]: {} Bytes. {}", obj.getVDS_CTLR_ID(), buffer3.array().length, NettyUtils.getRemoteAddress(channel));
					}
				}
			});
			obj.setStopImageResponse();
			String saveDir = ItsUtils.createUserDir("/images/");
			ItsUtils.saveByteArrayToFile(saveDir + obj.getVDS_CTLR_ID() + "_" + SysUtils.getSysTime() + ".jpg", buffer3.array());
		}
		else {
			VdsReqImage reqImage = new VdsReqImage((short)obj.getGROUP_NO(), (short)obj.getVDS_CTLR_LOCAL_NO());
			reqImage.setCameraNo(obj.getCameraNo());
			reqImage.setFrameNo(nextFrame);
			reqImage.makeCRC();
			ByteBuffer sendBuffer = reqImage.getByteBuffer();
			if (!obj.sendData(sendBuffer, 0, "vds_Image")) {
				log.error("[{}]. Job_Image: request data failed: total {}, frameNo {}", obj.getVDS_CTLR_ID(), total, nextFrame);
				obj.setStopImageResponse();
			} else {
				log.info("[{}]. Job_Image: next image request, total {}, current {}, next {}", obj.getVDS_CTLR_ID(), total, current, nextFrame);
			}
		}
		return 0;
	}

	public boolean sendCenterResponse(Channel channel, ByteBuffer sendBuff, TbVdsCtlr obj) {
		boolean result = false;
		log.error("[{}]. Job_Image: sendCenterResponse {} Bytes", obj.getVDS_CTLR_ID(), sendBuff.array().length);
		if (channel != null) {
			ChannelFuture f = channel.writeAndFlush(sendBuff);
			f.awaitUninterruptibly();
			if (f.isDone() || f.isSuccess()) {
				result = true;
			} else {
				log.error("[{}]. Job_Image: sendResponse: {} sendBytes, Failed. {}", obj.getVDS_CTLR_ID(), sendBuff.array().length, NettyUtils.getRemoteAddress(channel));
			}
		}
		return result;
	}
}
