package com.yizhi.application.course.controller;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.plugins.Page;
import com.yizhi.application.course.util.*;
import com.yizhi.application.course.vo.RichMediaVO;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.core.application.enums.InternationalEnums;
import com.yizhi.course.application.feign.MaterialClient;
import com.yizhi.course.application.vo.AudioVideoVO;
import com.yizhi.course.application.vo.MaterialDeleteVo;
import com.yizhi.course.application.vo.MaterialVo;
import com.yizhi.course.application.vo.domain.MaterialEntityVo;
import com.yizhi.util.application.domain.Response;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.log4j.Log4j2;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.mp3.MP3AudioHeader;
import org.jaudiotagger.audio.mp3.MP3File;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

/**
 * <p>
 * 素材库 前端控制器
 * </p>
 *
 * @author fulan123
 * @since 2018-03-19
 */
@Api(tags = "管理端-课程素材", description = "素材库接口")
@Log4j2
@RestController
@RequestMapping("/manage/material")
public class MaterialController {


    @Autowired
    ScormXMLImporter scormXMLImporter;

    @Autowired
    WebUpConvert webUpConvert;
    @Autowired
    DocPagesAsynchronizationDeal docPagesAsynchronizationDeal;
    @Autowired
    ScormAsynchronizationDeal scormAsynchronizationDeal;
    @Autowired
    VideoAsynchronizationDeal videoAsynchronizationDeal;
    @Autowired
    MaterialExport materialExport;

    private Logger LOG = LoggerFactory.getLogger(MaterialController.class);
    @Autowired
    private MaterialClient materialClient;

    @PostMapping("/save")
    @ApiOperation(value = "新增素材库", notes = "返回是否成功")
    public Response<String> insert(
            @ApiParam(name = "materialVo", value = "素材库vo", required = true) @RequestBody MaterialVo materialVo) {

        MaterialEntityVo material = new MaterialEntityVo();
        material.setOriginalFileUrl(materialVo.getOriginalFileUrl());
        material.setCode(new Date().getTime() + "");
        material.setName(materialVo.getName());
        material.setProducer(materialVo.getProducer());
        material.setSource(materialVo.getSource());
        material.setTags(materialVo.getTags());
        material.setType(materialVo.getType());
        //material.setSize(materialVo.getSize());
        material.setOriginalFile(materialVo.getOriginalFile());
        material.setExamId(materialVo.getExamId());
        material.setExamName(materialVo.getExamName());

        RequestContext requestContext = ContextHolder.get();
        String fullName = requestContext.getAccountFullName();
        String name = requestContext.getAccountName();
        material.setSiteId(requestContext.getSiteId());
        material.setCompanyId(requestContext.getCompanyId());
        material.setOrgId(requestContext.getOrgId());
        material.setCreateById(requestContext.getAccountId());
        material.setCreateByName(requestContext.getAccountName());
        material.setCreateTime(new Date());
        material.setDisplayMark(materialVo.getDisplayMark() != null ? materialVo.getDisplayMark() : 0);
        material.setWordType(materialVo.getWordType());
        if (material.getWordType() != null && material.getWordType() == 0) {
            material.setWord(StringUtils.isEmpty(fullName) ? name : fullName);
        } else if (material.getWordType() != null && material.getWordType() == 1) {
            material.setWord(materialVo.getWord());
        }
        //获取文件路径的文件大小进行存储设值
        InputStream in = null;
        HttpURLConnection conn = null;
        try {
            // 只有当originalFileUrl 有值才会去获取文件大小
            String originalFileUrl = materialVo.getOriginalFileUrl();
            if (!org.apache.commons.lang3.StringUtils.trimToEmpty(originalFileUrl).equals(org.apache.commons.lang3.StringUtils.EMPTY)) {
                URL url = new URL(originalFileUrl);
                //利用HttpURLConnection对象,我们可以从网络中获取网页数据.
                conn = (HttpURLConnection) url.openConnection();
                conn.setDoInput(true);
                conn.setRequestMethod("GET");
                conn.connect();
                //得到网络返回的输入流
                //in = conn.getInputStream();
                //int的方式得不到文件的大小，最大1.9G，会出现数据错误注释掉
                //int available = in.available();
                // log.info(available);
                //使用以下方式可以获取文件大小，精准度不是很完美
                long contentLengthLong = conn.getContentLengthLong();
                log.info(contentLengthLong);
                //进行存值
                material.setSize(String.valueOf(contentLengthLong));
            }

        } catch (Exception e) {
            LOG.error("新增素材库 信息--------------------------：{}", JSON.toJSONString(materialVo));
            LOG.error("异常信息={}", e);
            //e.printStackTrace();
        }

        //素材时长处理
        if (material.getType() == 1) {
            //音频 todo 压缩未处理
            materialVo.setFdUrl(materialVo.getOriginalFileUrl());
            materialVo.setLdUrl(materialVo.getOriginalFileUrl());
            materialVo.setSdUrl(materialVo.getOriginalFileUrl());
            //音频时长
            try {
                File file = scormXMLImporter.read(materialVo.getOriginalFileUrl(), "/home/file", materialVo.getOriginalFile());
                MP3File f = (MP3File) AudioFileIO.read(file);
                MP3AudioHeader audioHeader = (MP3AudioHeader) f.getAudioHeader();
                int time = audioHeader.getTrackLength();
                System.out.println("此视频时长为:" + time / 60 + "分" + time % 60 + "秒！");
                material.setTextHour(0);
                material.setTextMinute(time / 60);
                material.setTextSecond(time % 60);
                file.delete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            material.setTextHour(materialVo.getTextHour());
            material.setTextMinute(materialVo.getTextMinute());
            material.setTextSecond(materialVo.getTextSecond());
        }

        //应急视频处理
        if (material.getType() == 2) {
            if (StringUtils.isEmpty(materialVo.getFdUrl())) {
                materialVo.setFdUrl(materialVo.getOriginalFileUrl());
                materialVo.setLdUrl(materialVo.getOriginalFileUrl());
                materialVo.setSdUrl(materialVo.getOriginalFileUrl());
            }
        }

        Map<String, Object> map = new HashMap<>();
        map.put("material", material);
        map.put("action", "create");

        if (material.getType() == 1) {
            AudioVideoVO video = new AudioVideoVO();
            video.setExplanation(materialVo.getExplanation());
            video.setImage(materialVo.getImage());
            map.put("audio", video);
            videoAsynchronizationDeal.execute(map, Boolean.TRUE);
            return Response.ok("音频频素材已经在任务列表解析中！");
        }

        if (material.getType() == 2) {
            AudioVideoVO video = new AudioVideoVO();
            video.setExplanation(materialVo.getExplanation());
            video.setImage(materialVo.getImage());
            map.put("video", video);
            videoAsynchronizationDeal.execute(map, Boolean.TRUE);
            return Response.ok("视频素材已经在任务列表解析中！");
        }
        if (material.getType() == 3) {
            docPagesAsynchronizationDeal.execute(map, Boolean.TRUE);
            return Response.ok("文本素材已经在任务列表解析中！");
        }
        if (material.getType() == 5) {
            scormAsynchronizationDeal.execute(map, Boolean.TRUE);
            return Response.ok("scorm素材已经在任务列表解析中！");
        }
        //根据type处理
        Map<String, Object> materialMap = materialType(materialVo);
        if (map.containsKey("error")) {
            return Response.fail("error", map.get("error").toString());
        }
        map.putAll(materialMap);
        Boolean f = materialClient.insert(map);
        if (f) {
            return Response.ok("成功");
        }
        return Response.fail(InternationalEnums.MATERIALCONTROLLER1.getCode());
    }

    @PostMapping("/update")
    @ApiOperation(value = "素材库修改", notes = "返回是否成功")
    public Response<String> update(
            @ApiParam(name = "materialVo", value = "素材库vo", required = true) @RequestBody MaterialVo materialVo) {

        RequestContext requestContext = ContextHolder.get();
        String fullName = requestContext.getAccountFullName();
        String name = requestContext.getAccountName();
        MaterialEntityVo material = materialClient.view(Long.valueOf(materialVo.getId().trim()));
        String fileUrl = material.getOriginalFileUrl();
        boolean isNewUploadFile = true;
        if(Objects.nonNull(fileUrl) && fileUrl.equals(materialVo.getOriginalFileUrl())){
            isNewUploadFile = false;
        }else {
            material.setOriginalFileUrl(materialVo.getOriginalFileUrl());
        }
        material.setCode(materialVo.getCode());
        material.setName(materialVo.getName());
        material.setProducer(materialVo.getProducer());
        material.setSource(materialVo.getSource());
        material.setTags(materialVo.getTags());
        material.setType(materialVo.getType());
        material.setTextHour(materialVo.getTextHour());
        material.setTextMinute(materialVo.getTextMinute());
        material.setTextSecond(materialVo.getTextSecond());
        material.setOriginalFile(materialVo.getOriginalFile());
        material.setSize(materialVo.getSize());
        material.setExamId(materialVo.getExamId());
        material.setExamName(materialVo.getExamName());
        material.setDisplayMark(materialVo.getDisplayMark()!=null?materialVo.getDisplayMark():0);
        material.setWordType(materialVo.getWordType());
        if (material.getWordType()!=null&&material.getWordType()==0) {
            material.setWord(StringUtils.isEmpty(fullName)?name:fullName);
        }else if (material.getWordType()!=null&&material.getWordType()==1) {
            material.setWord(materialVo.getWord());
        }
        if (material.getDisplayMark()==0) {
            material.setWord("");
        }
        //素材时长处理
        if (material.getType() == 1 && isNewUploadFile) {
            // 音频 todo 压缩未处理
            materialVo.setFdUrl(materialVo.getOriginalFileUrl());
            materialVo.setLdUrl(materialVo.getOriginalFileUrl());
            materialVo.setSdUrl(materialVo.getOriginalFileUrl());
            // 音频时长
            try {
                File file = scormXMLImporter.read(materialVo.getOriginalFileUrl(), "/tmp", materialVo.getOriginalFile());
                MP3File f = (MP3File) AudioFileIO.read(file);
                MP3AudioHeader audioHeader = (MP3AudioHeader) f.getAudioHeader();
                int time = audioHeader.getTrackLength();
                System.out.println("此视频时长为:" + time / 60 + "分" + time % 60 + "秒！");
                material.setTextHour(0);
                material.setTextMinute(time / 60);
                material.setTextSecond(time % 60);
                file.delete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            material.setTextHour(materialVo.getTextHour());
            material.setTextMinute(materialVo.getTextMinute());
            material.setTextSecond(materialVo.getTextSecond());
        }


        //应急视频处理
        if (material.getType() == 2) {
            if (StringUtils.isEmpty(materialVo.getFdUrl())) {
                materialVo.setFdUrl(materialVo.getOriginalFileUrl());
                materialVo.setLdUrl(materialVo.getOriginalFileUrl());
                materialVo.setSdUrl(materialVo.getOriginalFileUrl());
            }
        }

        Map<String, Object> map = new HashMap<>();
        map.put("material", material);
        map.put("action", "update");

        if (material.getType() == 1) {
            AudioVideoVO video = new AudioVideoVO();
            video.setExplanation(materialVo.getExplanation());
            video.setImage(materialVo.getImage());
            map.put("audio", video);
            videoAsynchronizationDeal.execute(map, Boolean.TRUE);
            return Response.ok("音频素材已经在任务列表解析中！");
        }
        if (material.getType() == 2 && isNewUploadFile) {
            AudioVideoVO video = new AudioVideoVO();
            video.setExplanation(materialVo.getExplanation());
            video.setImage(materialVo.getImage());
            map.put("video", video);
            videoAsynchronizationDeal.execute(map, Boolean.TRUE);
            return Response.ok("视频素材已经在任务列表解析中！");
        }
        if (material.getType() == 3) {
            docPagesAsynchronizationDeal.execute(map, Boolean.TRUE);
            return Response.ok("文本素材已经在任务列表解析中！");
        }
        if (material.getType() == 5 && isNewUploadFile) {
            scormAsynchronizationDeal.execute(map, Boolean.TRUE);
            return Response.ok("scorm素材已经在任务列表解析中！");
        }
        //根据type处理
        Map<String, Object> materialMap = materialType(materialVo);
        if (materialMap.containsKey("error")) {
            return Response.fail("error", map.get("error").toString());
        }
        map.putAll(materialMap);
        Boolean f = materialClient.update(map);
        if (f) {
            return Response.ok("修改成功");
        }
        return Response.fail(InternationalEnums.DOCUMENTCLASSIFYCOMTROLLER3.getCode());
    }

    @PostMapping("/delete")
    @ApiOperation(value = "素材库删除", notes = "返回是否成功")
    public Response<String> delete(
            @RequestBody MaterialDeleteVo materialDeleteVo
    ) {
        List<Long> idList = new ArrayList<Long>();
        String[] idss = materialDeleteVo.getIds().split(",");
        for (String id : idss) {
            Long lid = Long.valueOf(id.trim());
            idList.add(lid);
        }
        Boolean f = materialClient.delete(idList);
        if (f) {
            return Response.ok("删除成功");
        } else {
            return Response.fail(InternationalEnums.MATERIALCONTROLLER2.getCode());
        }
    }

    @GetMapping("/get")
    @ApiOperation(value = "素材库信息查询", notes = "返回素材库信息", response = MaterialVo.class)
    public Response<MaterialVo> get(
            @ApiParam(name = "id", value = "主键id", required = true) @RequestParam(name = "id") Long id
    ) {
        MaterialVo materialVo = materialClient.get(id);
        return Response.ok(materialVo);
    }

    @PostMapping("/import")
    @ApiOperation(value = "素材库导入", notes = "返回是否成功")
    public Response<String> excleImport(
            @ApiParam(name = "fileurl", value = "excel文件上传到aliyunOSS库的文件url", required = true) @RequestParam(name = "fileurl") String fileurl,
            @ApiParam(name = "fileName", value = "文件名称，需要带后缀", required = true) @RequestParam(name = "fileName") String fileName
    ) {
        return Response.ok("暂时未定");
    }

    @GetMapping("/list")
    @ApiOperation(value = "素材库列表", notes = "返回素材可列表", response = MaterialEntityVo.class)
    public Response<Page<MaterialEntityVo>> list(
            @ApiParam(name = "name", value = "素材名称", required = false) @RequestParam(name = "name", required = false) String name,
            @ApiParam(name = "type", value = "素材类型  1音频 2 视频 3 文本 4 富媒体 5 Scrom", required = false) @RequestParam(name = "type", required = false) Integer type,
            @ApiParam(name = "source", value = "素材来源  1 外部采购 2 外部定制 3 内部定制 4 做课", required = false) @RequestParam(name = "source", required = false) Integer source,
            @ApiParam(name = "pageNo", value = "跳转页数,默认第一页", required = true) @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @ApiParam(name = "pageSize", value = "每页条数,默认20条", required = true) @RequestParam(name = "pageSize", defaultValue = "20") Integer pageSize
    ) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("pageNo", pageNo);
        map.put("pageSize", pageSize);
        map.put("name", name);
        map.put("type", type);
        map.put("source", source);
        RequestContext requestContext = ContextHolder.get();
        if (StringUtils.isEmpty(requestContext)) {
            map.put("companyId", 0l);
            map.put("siteId", 0l);
        } else {
            if (requestContext.isAdmin()) {
                map.put("companyId", requestContext.getCompanyId());
                map.put("siteId", requestContext.getSiteId());
            } else {
                map.put("companyId", requestContext.getCompanyId());
                map.put("siteId", requestContext.getSiteId());
                map.put("orgId", requestContext.getOrgIds());
            }
        }
        Page<MaterialEntityVo> page = materialClient.list(map);

        return Response.ok(page);
    }


    //通过类型 去执行相应的解析 1音频 2 视频 3 文本 4 富媒体 5 Scrom
    private Map<String, Object> materialType(MaterialVo materialVo) {
        Map<String, Object> map = new HashMap<String, Object>();
        switch (materialVo.getType()) {
            case 1:
                AudioVideoVO audio = new AudioVideoVO();
                audio.setExplanation(materialVo.getExplanation());
                audio.setFdUrl(materialVo.getFdUrl());
                audio.setSdUrl(materialVo.getSdUrl());
                audio.setImage(materialVo.getImage());
                audio.setLdUrl(materialVo.getLdUrl());
                map.put("audio", audio);
                break;
            case 2:
                AudioVideoVO video = new AudioVideoVO();
                video.setLdUrl(materialVo.getLdUrl());
                video.setFdUrl(materialVo.getFdUrl());
                video.setSdUrl(materialVo.getSdUrl());
                video.setImage(materialVo.getImage());
                map.put("video", video);
                break;
            case 4:
                RichMediaVO richMedia = new RichMediaVO();
                richMedia.setAuthor(materialVo.getAuthor());
                richMedia.setContent(materialVo.getContent());
                richMedia.setTitle(materialVo.getTitle());
                map.put("richMedia", richMedia);
                break;
        }
        return map;
    }

    @PostMapping("/export")
    @ApiOperation(value = "素材库导出", notes = "返回是否成功")
    public Response<String> excleExport(
    ) {

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("pageNo", 1);
        map.put("pageSize", 10000);
        RequestContext requestContext = ContextHolder.get();
        if (requestContext.isAdmin()) {
            map.put("companyId", requestContext.getCompanyId());
            map.put("siteId", requestContext.getSiteId());

        } else {
            map.put("companyId", requestContext.getCompanyId());
            map.put("siteId", requestContext.getSiteId());
            map.put("orgId", requestContext.getOrgIds());
        }

        List<MaterialEntityVo> dataAll = new ArrayList<>();
        int pageNo = 1;
        int dataSize = 0;
        do {
            map.put("pageNo", pageNo);
            Page<MaterialEntityVo> page = materialClient.list(map);
            List<MaterialEntityVo> data = page.getRecords();
            if (!CollectionUtils.isEmpty(data)) {
                dataSize = data.size();
                dataAll.addAll(data);
            } else {
                dataSize = 0;
            }
            pageNo++;
        } while (dataSize > 0);
        map.put("siteName", requestContext.getSiteName());
        map.put("list", dataAll);
        map.put("accountId", requestContext.getAccountId());
        LOG.info("开始素材导出异步执行");
        materialExport.execute(map, Boolean.TRUE);
        return Response.ok();
    }

    @GetMapping("/scormList")
    @ApiOperation(value = "查询素材列表  ( Scorm课程 )", response = MaterialEntityVo.class)
    public Response<Page<MaterialEntityVo>> queryScormCourseList(
            @ApiParam(name = "name", value = "素材名称", required = false) @RequestParam(name = "name", required = false) String name,
            @ApiParam(name = "type", value = "素材类型  1音频 2 视频 3 文本 4 富媒体 5 Scrom", required = false) @RequestParam(name = "type", required = false) Integer type,
            @ApiParam(name = "source", value = "素材来源  1 外部采购 2 外部定制 3 内部定制 4 做课", required = false) @RequestParam(name = "source", required = false) Integer source,
            @ApiParam(name = "pageNo", value = "跳转页数,默认第一页", required = true) @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @ApiParam(name = "pageSize", value = "每页条数,默认20条", required = true) @RequestParam(name = "pageSize", defaultValue = "20") Integer pageSize
    ) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("pageNo", pageNo);
        map.put("pageSize", pageSize);
        map.put("name", name);
        map.put("type", type);
        map.put("source", source);
        RequestContext requestContext = ContextHolder.get();
        if (StringUtils.isEmpty(requestContext)) {
            map.put("companyId", 0l);
            map.put("siteId", 0l);
        } else {
            if (requestContext.isAdmin()) {
                map.put("companyId", requestContext.getCompanyId());
                map.put("siteId", requestContext.getSiteId());
            } else {
                map.put("companyId", requestContext.getCompanyId());
                map.put("siteId", requestContext.getSiteId());
                map.put("orgId", requestContext.getOrgIds());
            }
        }

        Page<MaterialEntityVo> page = materialClient.queryScormCourseList(map);
        return Response.ok(page);
    }

    @GetMapping("/commonList")
    @ApiOperation(value = "查询素材列表  ( Scorm课程 )", response = MaterialEntityVo.class)
    public Response<Page<MaterialEntityVo>> queryCommonCourseList(
            @ApiParam(name = "name", value = "素材名称", required = false) @RequestParam(name = "name", required = false) String name,
            @ApiParam(name = "type", value = "素材类型  1音频 2 视频 3 文本 4 富媒体 5 Scrom", required = false) @RequestParam(name = "type", required = false) Integer type,
            @ApiParam(name = "source", value = "素材来源  1 外部采购 2 外部定制 3 内部定制 4 做课", required = false) @RequestParam(name = "source", required = false) Integer source,
            @ApiParam(name = "pageNo", value = "跳转页数,默认第一页", required = true) @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @ApiParam(name = "pageSize", value = "每页条数,默认20条", required = true) @RequestParam(name = "pageSize", defaultValue = "20") Integer pageSize,
            @ApiParam(name = "excludType", value = "排除的素材类型", required = false) @RequestParam(name = "excludType", required = false) Integer excludType
    ) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("pageNo", pageNo);
        map.put("pageSize", pageSize);
        map.put("name", name);
        map.put("type", type);
        map.put("source", source);
        map.put("excludType", excludType);
        RequestContext requestContext = ContextHolder.get();
        if (StringUtils.isEmpty(requestContext)) {
            map.put("companyId", 0l);
            map.put("siteId", 0l);
        } else {
            if (requestContext.isAdmin()) {
                map.put("companyId", requestContext.getCompanyId());
                map.put("siteId", requestContext.getSiteId());
            } else {
                map.put("companyId", requestContext.getCompanyId());
                map.put("siteId", requestContext.getSiteId());
                map.put("orgId", requestContext.getOrgIds());
            }
        }

        Page<MaterialEntityVo> page = materialClient.queryCommonCourseList(map);
        return Response.ok(page);
    }
    /***
     *  导出素材清单
     * @param classifyId
     * @return
     */
    @GetMapping("/list/export")
    public Response<String> materialListExport(@RequestParam(required = false, value = "type", defaultValue = "0") Integer type,
                                                  @ApiParam(name = "name", value = "课程名称或作者", required = false) @RequestParam(name = "name", required = false) String name,
                                                  @ApiParam(name = "classifyId", value = "分类id ", required = false) @RequestParam(name = "classifyId", required = false) Long classifyId,
                                                  @ApiParam(name = "shelves", value = "0 未上架 1 已上架 2 草稿", required = false) @RequestParam(name = "shelves", required = false) Integer shelves,
                                                  @ApiParam(name = "courseType", value = "课程类型", required = false) @RequestParam(required = false, value = "courseType") Integer courseType) {

        return Response.ok(materialClient.materialListExport(type, name, classifyId, shelves, courseType).get("result").toString());
    }

}

