package com.pdaaphm.biz.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.pdaaphm.biz.domain.AlgorithmIoField;
import com.pdaaphm.biz.domain.AlgorithmSubType;
import com.pdaaphm.biz.domain.SubAlgorithm;
import com.pdaaphm.biz.dto.AlgorithmDTO;
import com.pdaaphm.biz.dto.RequestDTO;
import com.pdaaphm.biz.dto.SubAlgorithmDTO;
import com.pdaaphm.biz.factory.AlgorithmFactory;
import com.pdaaphm.biz.mapper.AlgorithmIoFieldMapper;
import com.pdaaphm.biz.mapper.AlgorithmSubTypeMapper;
import com.pdaaphm.biz.mapper.SubAlgorithmMapper;
import com.pdaaphm.biz.service.RunAlgorithmService;
import com.pdaaphm.common.config.PadaphmConfig;
import com.pdaaphm.common.utils.DateUtils;
import com.pdaaphm.common.utils.file.FileUploadUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.pdaaphm.biz.mapper.AlgorithmMapper;
import com.pdaaphm.biz.domain.Algorithm;
import com.pdaaphm.biz.service.IAlgorithmService;
import org.springframework.util.CollectionUtils;

/**
 * 算法Service业务层处理
 *
 * @author xlk
 * @date 2023-07-26
 */
@Service
public class AlgorithmServiceImpl implements IAlgorithmService
{
    @Autowired
    private AlgorithmMapper algorithmMapper;
    @Autowired
    private SubAlgorithmMapper subAlgorithmMapper;
    @Autowired
    private AlgorithmIoFieldMapper algorithmIoFieldMapper;
    @Autowired
    private AlgorithmFactory algorithmFactory;
    @Autowired
    private AlgorithmSubTypeMapper algorithmSubTypeMapper;

    /**
     * 查询算法
     *
     * @param id 算法主键
     * @return 算法
     */
    @Override
    public Algorithm selectAlgorithmById(Long id)
    {
        return algorithmMapper.selectAlgorithmById(id);
    }

    /**
     * 查询算法对象
     *
     * @param id 算法主键
     * @return 算法
     */
    @Override
    public AlgorithmDTO getAlgorithmDto(Long id)
    {
        Algorithm algorithm = this.selectAlgorithmById(id);
        AlgorithmDTO algorithmDto = new AlgorithmDTO();
        List<SubAlgorithmDTO> l = algorithmIoFieldMapper.getIoSubList(algorithm.getSubTypeId(),id);
        BeanUtils.copyProperties(algorithm,algorithmDto);
        algorithmDto.setIoSubList(l);
        return algorithmDto;
    }

    /**
     * 查询算法列表
     *
     * @param algorithm 算法
     * @return 算法
     */
    @Override
    public List<Algorithm> selectAlgorithmList(Algorithm algorithm)
    {
        return algorithmMapper.selectAlgorithmList(algorithm);
    }

    /**
     * 新增算法
     *
     * @param algorithm 算法
     * @return 结果
     */
    @Override
    public int insertAlgorithm(Algorithm algorithm)
    {
        algorithm.setCreateTime(DateUtils.getNowDate());
        algorithm.setStatus(Algorithm.createdCode);
        return algorithmMapper.insertAlgorithm(algorithm);
    }

    @Override
    public int addOrUpdateDto(AlgorithmDTO algorithmDto) {
        int res;
        Algorithm algorithm = new Algorithm();
        BeanUtils.copyProperties(algorithmDto,algorithm);
        if(algorithmDto.getId() == null){
            res = this.insertAlgorithm(algorithm);
        } else {
            res = this.updateAlgorithm(algorithm);
        }
        List<SubAlgorithmDTO> ioSubList = algorithmDto.getIoSubList();
        SubAlgorithm subAlgorithm = new SubAlgorithm();
        for(int i = 0; i < ioSubList.size(); i++){
            SubAlgorithmDTO subAlgorithmDTO = ioSubList.get(i);
            BeanUtils.copyProperties(subAlgorithmDTO,subAlgorithm);
            subAlgorithm.setAlgorithmId(algorithm.getId());
            if(subAlgorithmDTO.getId() == null){
                subAlgorithmMapper.insertSubAlgorithm(subAlgorithm);
            } else {
                subAlgorithmMapper.updateSubAlgorithm(subAlgorithm);
            }
        }
        return res;
    }

    /**
     * 修改算法
     *
     * @param algorithm 算法
     * @return 结果
     */
    @Override
    public int updateAlgorithm(Algorithm algorithm)
    {
        algorithm.setUpdateTime(DateUtils.getNowDate());
        return algorithmMapper.updateAlgorithm(algorithm);
    }

    /**
     * 批量删除算法
     *
     * @param ids 需要删除的算法主键
     * @return 结果
     */
    @Override
    public int deleteAlgorithmByIds(Long[] ids)
    {
        return algorithmMapper.deleteAlgorithmByIds(ids);
    }

    /**
     * 删除算法信息
     *
     * @param id 算法主键
     * @return 结果
     */
    @Override
    public int deleteAlgorithmById(Long id)
    {
        return algorithmMapper.deleteAlgorithmById(id);
    }

    @Override
    public List<Map> getOption() { return algorithmMapper.getOption(); }

    @Async
    @Override
    public void runAlgorithms(Long id) throws IOException {
        algorithmMapper.updateStatusById(id, Algorithm.runningCode);
        Date startTime = DateUtils.getNowDate();
        algorithmMapper.updateStartTimeById(id, startTime);
        List<Map> list = algorithmMapper.selectUrlAndAddressById(id);
        Algorithm algorithm = this.selectAlgorithmById(id);
        AlgorithmSubType algorithmSubType = algorithmSubTypeMapper.selectAlgorithmSubTypeById(algorithm.getSubTypeId());
        RunAlgorithmService runAlgorithmService = algorithmFactory.createRun(algorithmSubType.getRunType());
        if(CollectionUtils.isEmpty(list)){
            return;
        }
        List<String> docAddress = new ArrayList<>(list.size());
        List<String> resultAddress = new ArrayList<>(list.size());
        String prefix = PadaphmConfig.getProfile();
        String prefix2 = PadaphmConfig.getResultPath();
        int j = 1;
        for (int i = 0; i < list.size(); i++) {
            if (AlgorithmIoField.inputCode.equals(list.get(i).get("type"))) {
                String s = (String)list.get(i).get("path");
                if (s.startsWith("/profile")) {
                    s = s.replace("/profile", prefix);
                }
                docAddress.add(s);
            }
            else {
                String fileName = "result" + j;
                j++;
                String filePrefix = PadaphmConfig.getResultFilePath();
                String fileNameFinal = FileUploadUtils.upload(filePrefix, fileName);
                if (fileNameFinal.startsWith("/profile")) {
                    fileNameFinal = fileNameFinal.replace("/profile", prefix2);
                }
                resultAddress.add(fileNameFinal);
            }
        }
        RequestDTO requestDto = new RequestDTO();
        requestDto.setDocList(docAddress);
        requestDto.setResultList(resultAddress);
        runAlgorithmService.runAlgorithm(id, (String)list.get(0).get("url"), requestDto);
        Date completedTime = DateUtils.getNowDate();
        algorithmMapper.updateCompletedTimeById(id, completedTime);
        Long diffInMillies = completedTime.getTime() - startTime.getTime();
        Long costSecond = TimeUnit.MILLISECONDS.toSeconds(diffInMillies);
        algorithmMapper.updateCostSecondById(id, costSecond);
        algorithmMapper.updateStatusById(id, Algorithm.completedCode);
        return;
    }
}
