/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.smartapplication.vcdevice.controller;

import cn.hutool.core.lang.Assert;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.community.agency.entity.Agency;
import org.springblade.community.agency.service.IAgencyService;
import org.springblade.community.building.entity.Building;
import org.springblade.community.building.service.IBuildingService;
import org.springblade.community.residential.entity.Residential;
import org.springblade.community.residential.service.IResidentialService;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.system.service.IParamService;
import org.springblade.smartapplication.vcdevice.conf.ZlmConfig;
import org.springblade.smartapplication.vcdevice.dto.VideoCloudDeviceDTO;
import org.springblade.smartapplication.vcdevice.entity.VideoCloudDevice;
import org.springblade.smartapplication.vcdevice.service.IVideoCloudDeviceService;
import org.springblade.smartapplication.vcdevice.vo.VideoCloudDeviceVO;
import org.springblade.smartapplication.vcdevice.wrapper.VideoCloudDeviceWrapper;
import org.springblade.system.orgposition.entity.OrgPosition;
import org.springblade.system.orgposition.service.IOrgPositionService;
import org.springblade.utils.QueryWrapperUtil;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 *  控制器
 *
 * @author BladeX
 * @since 2020-11-12
 */
@RestController
@AllArgsConstructor
@RequestMapping("yc_video_cloud_device/videoclouddevice")
@Api(value = "视频云设备", tags = "视频云设备")
@Slf4j
public class VideoCloudDeviceController extends BladeController {

	private IVideoCloudDeviceService videoCloudDeviceService;
	private IResidentialService residentialService;
	private IBuildingService buildingService;
	private IOrgPositionService orgPositionService;
	private IAgencyService agencyService;
	private IParamService paramService;

	/**
	 * 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入videoCloudDevice")
	public R<VideoCloudDeviceVO> detail(VideoCloudDevice videoCloudDevice) {
		VideoCloudDevice detail = videoCloudDeviceService.getOne(Condition.getQueryWrapper(videoCloudDevice));
		return R.data(VideoCloudDeviceWrapper.build().entityVO(detail));
	}

	/**
	 * 详情
	 */
	@GetMapping("/getByResidential")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入videoCloudDevice")
	public R getByResidential(@RequestParam(required = false) String residentialName,BladeUser bladeUser) {
		String deptId = bladeUser.getDeptId();
		String[] deptIds = deptId.split(",");
		LambdaQueryWrapper<VideoCloudDevice> wrapper = Condition.getQueryWrapper(new VideoCloudDevice()).lambda();
		List<String> vcAccountNames = new ArrayList<>();
		int size =0;
		for(int i=0;i<deptIds.length;i++){
			OrgPosition orgPosition = orgPositionService.getOne(new QueryWrapper<>(new OrgPosition()).lambda().eq(OrgPosition::getOrgId,deptIds[i]));
			String vcDeviceAccountName = orgPosition.getVcDeviceAccountName();
			String[] split = vcDeviceAccountName.split(",");

			for(int j=0;j<split.length;j++){
				if(!vcAccountNames.contains(split[j])){
					vcAccountNames.add(split[j]);
				}
			}
		}
		List<VideoCloudDevice> list = videoCloudDeviceService.getBaseMapper().selectList(wrapper.in(VideoCloudDevice::getAccountName,vcAccountNames));
		return R.data(list);
	}

	/**
	 * 详情
	 */
	@GetMapping("/getByResidentialAndDeviceName")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "根据小区或者设备名称模糊匹配视频云设备", notes = "传入videoCloudDevice")
	public R getByResidentialAndDeviceName(@RequestParam(required = false) Long residentialId,@RequestParam(required = false) Long buildingId,@RequestParam(required = false) Integer type,@RequestParam(required = false) String deviceName,BladeUser bladeUser) {
		String deptId = bladeUser.getDeptId();
		String[] deptIds = deptId.split(",");
		LambdaQueryWrapper<VideoCloudDevice> wrapper = Condition.getQueryWrapper(new VideoCloudDevice()).lambda();

		for (int i = 0; i < deptIds.length; i++) {
			OrgPosition orgPosition = orgPositionService.getBaseMapper().selectOne(new QueryWrapper<>(new OrgPosition()).lambda().eq(OrgPosition::getOrgId, deptIds[i]));
			if (i == 0) {
				wrapper.like(VideoCloudDevice::getOrgPosition,orgPosition.getOrgPosition());
			}else{
				wrapper.or().like(VideoCloudDevice::getOrgPosition,orgPosition.getOrgPosition());
			}
		}
		if(residentialId !=null){
			wrapper.eq(VideoCloudDevice::getResidentialId,residentialId);
			if(buildingId != null){
				wrapper.eq(VideoCloudDevice::getBuildingId,buildingId);
			}
		}
		if(deviceName!=null){
			wrapper.like(VideoCloudDevice::getDeviceName, deviceName);
		}
		if(type != null){
			wrapper.eq(VideoCloudDevice::getType,type);
		}
		List<VideoCloudDevice> list = videoCloudDeviceService.getBaseMapper().selectList(wrapper.eq(VideoCloudDevice::getTenantId,bladeUser.getTenantId()));
		return R.data(list);
	}

	/**
	 * 分页
	 */
	@GetMapping("/list")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "分页", notes = "传入videoCloudDevice")
	public R<IPage<VideoCloudDeviceVO>> list(@RequestParam Map<String,Object> videoCloudDevice, Query query, BladeUser bladeUser) {
//		String deptId = bladeUser.getDeptId();
//		String[] deptIds = deptId.split(",");
//		LambdaQueryWrapper<VideoCloudDevice> wrapper = Condition.getQueryWrapper(videoCloudDevice,VideoCloudDevice.class).lambda();
//		List<String> vcAccountNames = new ArrayList<>();
//		int size =0;
//		for(int i=0;i<deptIds.length;i++){
//			OrgPosition orgPosition = orgPositionService.getOne(new QueryWrapper<>(new OrgPosition()).lambda().eq(OrgPosition::getOrgId,deptIds[i]));
//			String vcDeviceAccountName = orgPosition.getVcDeviceAccountName();
//			String[] split = vcDeviceAccountName.split(",");
//
//			for(int j=0;j<split.length;j++){
//				if(!vcAccountNames.contains(split[j])){
//					vcAccountNames.add(split[j]);
//				}
//			}
//		}
		LambdaQueryWrapper<VideoCloudDevice> wrapper = new QueryWrapperUtil<VideoCloudDevice>().getBasicQueryWrapperByMap(VideoCloudDevice::getOrgPosition, videoCloudDevice, new VideoCloudDevice(), bladeUser, orgPositionService);
		IPage<VideoCloudDevice> pages = videoCloudDeviceService.page(Condition.getPage(query),wrapper);
		return R.data(VideoCloudDeviceWrapper.build().pageVO(pages));
	}

	/**
	 * 自定义分页
	 */
	@GetMapping("/page")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "分页", notes = "传入videoCloudDevice")
	public R<IPage<VideoCloudDeviceVO>> page(VideoCloudDeviceVO videoCloudDevice, Query query) {
		IPage<VideoCloudDeviceVO> pages = videoCloudDeviceService.selectVideoCloudDevicePage(Condition.getPage(query), videoCloudDevice);
		return R.data(pages);
	}

	/**
	 * 根据楼栋查询-分页
	 */
	@GetMapping("/pageByBuilding")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "分页", notes = "传入videoCloudDevice")
	public R<IPage<VideoCloudDeviceVO>> pageByBuilding(VideoCloudDeviceDTO videoCloudDeviceDTO, Query query) {
		Building building = this.buildingService.getById(videoCloudDeviceDTO.getBuildingId());
		Assert.notNull(building,"该楼栋不存在");
		String deviceName = building.getResidentialName() + building.getName();
		VideoCloudDeviceVO videoCloudDevice = new VideoCloudDeviceVO();
		BeanUtil.copyProperties(videoCloudDeviceDTO,videoCloudDevice);
		videoCloudDevice.setDeviceName(deviceName);
		IPage<VideoCloudDeviceVO> pages = videoCloudDeviceService.selectVideoCloudDevicePage(Condition.getPage(query), videoCloudDevice);
		return R.data(pages);
	}

	/**
	 * 新增
	 */
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增", notes = "传入videoCloudDevice")
	public R save(@Valid @RequestBody VideoCloudDevice videoCloudDevice) {
		return R.status(videoCloudDeviceService.save(videoCloudDevice));
	}

	/**
	 * 修改
	 */
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入videoCloudDevice")
	public R update(@Valid @RequestBody VideoCloudDevice videoCloudDevice) {

		if (videoCloudDevice.getResidentialId() != null) {
			Residential residential = residentialService.getById(videoCloudDevice.getResidentialId());
			if (residential != null) {
				Agency agency = agencyService.getById(residential.getAgencyId());
				videoCloudDevice.setOrgPosition(residential.getOrgPosition() + "/" + videoCloudDevice.getId());
				videoCloudDevice.setResidentialName(residential.getName());
				videoCloudDevice.setAgencyId(residential.getAgencyId());
				videoCloudDevice.setAgencyName(agency.getAgencyName());
				videoCloudDevice.setTenantId(agency.getTenantId());
			} else {
				return R.fail("需要绑定的区域不存在");
			}
		}
		if (videoCloudDevice.getBuildingId() != null) {
			Building building = buildingService.getById(videoCloudDevice.getBuildingId());
			if (building != null) {
				videoCloudDevice.setBuildingName(building.getName());
			} else {
				return R.fail("需要绑定的楼栋不存在");
			}
		}

		return R.status(videoCloudDeviceService.updateById(videoCloudDevice));
	}

	/**
	 * 新增或修改
	 */
	@PostMapping("/submit")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "新增或修改", notes = "传入videoCloudDevice")
	public R submit(@Valid @RequestBody VideoCloudDevice videoCloudDevice) {

			//判断是否为第三方平台调用
			if(videoCloudDevice.getId()==null&&videoCloudDevice.getOldId()!=null){
				VideoCloudDevice one = videoCloudDeviceService.getBaseMapper().selectOne(new QueryWrapper<>(new VideoCloudDevice()).lambda().eq(VideoCloudDevice::getOldId, videoCloudDevice.getOldId()));
				if(one != null){//该视频云设备之前已经推送过
					videoCloudDevice.setId(one.getId());
					return R.status(videoCloudDeviceService.updateById(videoCloudDevice));
				}else{//该视频云设备从未推送过
					return R.status(videoCloudDeviceService.save(videoCloudDevice));
				}
			}else{//本平台创建
				return R.status(videoCloudDeviceService.saveOrUpdate(videoCloudDevice));
			}
	}


	/**
	 * 删除
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(videoCloudDeviceService.deleteLogic(Func.toLongList(ids)));
	}


	/**
	 * 设置视频云设备的orgPosition
	 *
	 * @return
	 */
	@PostMapping("/setOrgPosition")
	public R setOrgPosition(){
		List<VideoCloudDevice> videoCloudDevices = videoCloudDeviceService.getBaseMapper().selectList(new QueryWrapper<>(new VideoCloudDevice()));

		for(int i=0;i<videoCloudDevices.size();i++){
			VideoCloudDevice videoCloudDevice = videoCloudDevices.get(i);
			if(videoCloudDevice.getResidentialId()!=null){
				Residential residential = residentialService.getById(videoCloudDevice.getResidentialId());
				videoCloudDevice.setOrgPosition(residential.getOrgPosition()+"/"+videoCloudDevice.getId());
				videoCloudDeviceService.updateById(videoCloudDevice);
			}else{
				List<Residential> residentials = residentialService.getBaseMapper().selectList(new QueryWrapper<>(new Residential()));
				for(int j=0;j<residentials.size();j++){
					if(videoCloudDevice.getDeviceName().contains(residentials.get(j).getName())){
						videoCloudDevice.setResidentialId(residentials.get(j).getId());
						videoCloudDevice.setOrgPosition(residentials.get(j).getOrgPosition()+"/"+videoCloudDevice.getId());
						videoCloudDeviceService.updateById(videoCloudDevice);
						break;
					}
				}
			}

		}

		return  new R();

	}

	/**
	 * 根据所属账号获取视频云列表
	 * @param accountName
	 * @return
	 */
	@GetMapping("/getVCDeviceByAccountName")
	public R<List<VideoCloudDevice>> getVCDeviceByAccountName(String accountName){
		List<VideoCloudDevice> videoCloudDevices = videoCloudDeviceService.getBaseMapper().selectList(new QueryWrapper<>(new VideoCloudDevice()).lambda().eq(VideoCloudDevice::getAccountName, accountName));
		return R.data(videoCloudDevices);
	}


	/**
	 * 视频云批量绑定小区->楼栋
	 * @param deviceIds
	 * @return
	 */
	@PostMapping("/bindResidentialBatch")
	public R bindResidentialBatch(@RequestParam List<Long> deviceIds,@RequestParam Long residentialId,@RequestParam(required = false) Long buildingId){

		for(int i = 0;i<deviceIds.size();i++){
			VideoCloudDevice videoCloudDevice = videoCloudDeviceService.getById(deviceIds.get(i));
			videoCloudDevice.setResidentialId(residentialId);
			if(buildingId != null){
				videoCloudDevice.setBuildingId(buildingId);
			}
			videoCloudDeviceService.updateById(videoCloudDevice);
		}
		return R.status(true);
	}
	/**
	 * 删除
	 */
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "推流查询", notes = "传入deviceNum")
	@PostMapping("/queryStream")
	public R queryStream(@ApiParam(value = "设备编码", required = true) @RequestParam String deviceNum){
		return R.status(true);
	}

	/**
	 * 通过指定账号同步设备
	 */
	@PostMapping("/syncByAccount")
	@ApiOperationSupport(order = 11)
	@ApiOperation(value = "通过指定账号同步设备", notes = "传入accountName")
	public R syncByAccount(@ApiParam(value = "视频云账号", required = true) @RequestParam(value = "accountName") String accountName)  {
		R result = videoCloudDeviceService.syncByAccountV3(accountName);
		return result;
	}

	/**
	 * 通过指定账号同步设备
	 */
	@PostMapping("/syncByDevice")
	@ApiOperationSupport(order = 12)
	@ApiOperation(value = "通过指定账号同步设备")
	public R syncByDevice(@ApiParam(value = "视频云账号", required = true) @RequestParam(value = "accountName") String accountName,
											@ApiParam(value = "视频云设备编号", required = true) @RequestParam(value = "deviceNum") String deviceNum) {
		R result = this.videoCloudDeviceService.syncByDeviceV3(accountName, deviceNum);
		return result;
	}

	/**
	 * 根据指定设备编号获取视频云播放地址
	 */
	@GetMapping("/getVideoUrl")
	@ApiOperationSupport(order = 13)
	@ApiOperation(value = "通过指定账号同步设备")
	public R<String> getVideoUrl(@ApiParam(value = "视频云账号", required = true) @RequestParam(value = "accountName") String accountName,
			                               @ApiParam(value = "视频云设备编号", required = true) @RequestParam(value = "deviceNum") String deviceNum,
											@RequestParam(value = "networkType", required = false) String networkType) {
		R<String> result = this.videoCloudDeviceService.getVideoUrlV3(accountName, deviceNum, networkType);
		return result;
	}

	/**
	 * 批量同步设备
	 */
	@PostMapping("/syncByDeviceBatch")
	@ApiOperationSupport(order = 14)
	@ApiOperation(value = "批量获取设备播放地址")
	public R syncByDeviceBatch(@ApiParam(value = "视频云设备编号", required = true) @RequestParam(value = "ids") String ids) {
		List<Long> idList = Func.toLongList(ids);
		R result = this.videoCloudDeviceService.syncByDeviceBatch(idList);
		return result;
	}

	/**
	 * 批量获取设备播放地址
	 */
	@PostMapping("/getVideoUrlBatch")
	@ApiOperationSupport(order = 15)
	@ApiOperation(value = "批量获取设备播放地址")
	public R getVideoUrlBatch(@ApiParam(value = "视频云设备编号", required = true) @RequestParam(value = "ids") String ids) {
		List<Long> idList = Func.toLongList(ids);
		R result = this.videoCloudDeviceService.getVideoUrlBatch(idList);
		return result;
	}

	/**
	 * 停止推流
	 */
	@PostMapping("/stopPlay")
	@ApiOperationSupport(order = 16)
	@ApiOperation(value = "停止推流")
	public R stopPlay(@RequestParam(value = "deviceNum") String deviceNum, @RequestParam(value = "url") String url) {
		VideoCloudDevice videoCloudDevice = this.videoCloudDeviceService.getByDeviceNum(deviceNum);
		String requestUrl = url + videoCloudDevice.getRtspUrl();
		String response = HttpUtil.get(requestUrl);
		JSONObject jsonObject = JSON.parseObject(response);
		if(jsonObject.getInteger("code") == 200){
			return R.success("停止成功");
		}else{
			return R.fail(jsonObject.getString("msg"));
		}
	}

	/**
	 * 开始拉流代理或者ffmpeg代理
	 */
	@PostMapping("/play")
	@ApiOperationSupport(order = 17)
	@ApiOperation(value = "开始拉流代理或者ffmpeg代理")
	public R play(@RequestParam(value = "deviceNum") String deviceNum) {
		String playMode = paramService.getValue("play_mode");
		switch (playMode){
			case "proxy":
				return this.videoCloudDeviceService.zlmPlayProxy(deviceNum);
			case "ffmpeg":
				return this.videoCloudDeviceService.zlmPlayFFmpeg(deviceNum);
			default:
				return this.videoCloudDeviceService.zlmPlayFFmpeg(deviceNum);
		}
	}

	/**
	 * 停止拉流代理或者ffmpeg代理
	 */
	@PostMapping("/stop")
	@ApiOperationSupport(order = 17)
	@ApiOperation(value = "停止拉流代理或者ffmpeg代理")
	public R stop(@RequestParam(value = "deviceNum") String deviceNum) {
		String playMode = paramService.getValue("play_mode");
		switch (playMode){
			case "proxy":
				return this.videoCloudDeviceService.zlmStopProxy(deviceNum);
			case "ffmpeg":
				return this.videoCloudDeviceService.zlmStopFFmpeg(deviceNum);
			default:
				return this.videoCloudDeviceService.zlmStopFFmpeg(deviceNum);
		}
	}

	/**
	 * 开始拉流代理
	 */
	@PostMapping("/zlmPlay")
	@ApiOperationSupport(order = 17)
	@ApiOperation(value = "停止推流")
	public R zlmPlay(@RequestParam(value = "deviceNum") String deviceNum) {
		return this.videoCloudDeviceService.zlmPlayProxy(deviceNum);
	}

	/**
	 * 停止拉流代理
	 */
	@PostMapping("/zlmStop")
	@ApiOperationSupport(order = 18)
	@ApiOperation(value = "停止推流")
	public R zlmStop(@RequestParam(value = "deviceNum") String deviceNum) {
		return this.videoCloudDeviceService.zlmStopProxy(deviceNum);
	}

	/**
	 * 开始ffmpeg拉流代理
	 */
	@PostMapping("/zlmPlayFFmpeg")
	@ApiOperationSupport(order = 19)
	@ApiOperation(value = "停止推流")
	public R zlmPlayFFmpeg(@RequestParam(value = "deviceNum") String deviceNum) {
		return this.videoCloudDeviceService.zlmPlayFFmpeg(deviceNum);
	}

	/**
	 * 停止ffmpeg拉流代理
	 */
	@PostMapping("/zlmStopFFmpeg")
	@ApiOperationSupport(order = 20)
	@ApiOperation(value = "停止推流")
	public R zlmStopFFmpeg(@RequestParam(value = "deviceNum") String deviceNum) {
		return this.videoCloudDeviceService.zlmStopFFmpeg(deviceNum);
	}
}
