package com.gx.obe.management.thread;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.eclipse.swt.core.CallBack;
import org.eclipse.swt.core.utils.MessageCallBack;

import com.gx.obe.boq.AnalyzeBOQListener;
import com.gx.obe.boq.AnalyzeBOQThread;
import com.gx.obe.common.file.entity.BidFile;
import com.gx.obe.common.file.enumeration.FileConstants;
import com.gx.obe.util.utils.CollectionUtils;
import com.gx.obe.util.utils.DateUtils;
import com.gx.obe.web.entity.Supplier;
import com.gx.obe.web.entity.tender.TenderProjectEntity;
import com.gx.obe.web.service.SupplierService;
import com.gx.obe.web.service.boq.ConstructProjectService;

/**
 * @Description: 批量导入工程量清单
 * @author chenxw
 */
public class ImportBillOfQuantitiesThread implements Runnable {
    
    private SupplierService supplierService = new SupplierService();
    private ConstructProjectService constructProjectService = new ConstructProjectService();
    private Thread thread;
    private TenderProjectEntity tenderProject;
    private MessageCallBack messageCallBack;
    private ExecutorService analyzeBOQThreadPool;
    private ExecutorService saveBOQThreadPool;
    private List<AnalyzeBOQThread> analyzeBOQThreadList = new ArrayList<AnalyzeBOQThread>();
    
    private List<String> notFoundList = new ArrayList<String>();
    private List<String> successList = new ArrayList<String>();
    private List<String> failList = new ArrayList<String>();
    
    /**
     * @author chenxw
     * @param tenderProject
     * @param callBack
     */
    public ImportBillOfQuantitiesThread(TenderProjectEntity tenderProject, CallBack callBack) {
        this.tenderProject = tenderProject;
        this.messageCallBack = new MessageCallBack(callBack);
    }
    
    public void run() {
        notFoundList.clear();
        
        Map<String, Supplier> map = new HashMap<String, Supplier>();
        File billBiddingFile = new File(FileConstants.getBiddingFilePath(tenderProject.getId()).concat(FileConstants.BILL_XML));
        if (billBiddingFile.exists() && billBiddingFile.isFile()) {
            map.put(billBiddingFile.getAbsolutePath(), null);
        } else {
            notFoundList.add("招标单位");
        }
        List<Supplier> suppliers = supplierService.getAllSupplierList(tenderProject.getId());
        if (CollectionUtils.isNotNull(suppliers)) for (Supplier supplier : suppliers) {
            File supplierBidFile = BidFile.getSupplierBidBillFile(supplier.getTenderId(), supplier.getId(), FileConstants.XML);
            if (null != supplierBidFile && supplierBidFile.exists()) {
                map.put(supplierBidFile.getAbsolutePath(), supplier);
            } else {
                notFoundList.add(supplier.getSupplierName());
            }
        }
        if (map != null && !map.isEmpty()) {
            importBillOfQuantities(map);
        } else {
            messageCallBack.callBackMsg(false, "没有可解析的工程量清单！");
        }
        messageCallBack.after();
    }
    
    /**
     * @Description: 批量导入工程量清单
     * @author chenxw
     * @param map
     */
    private void importBillOfQuantities(Map<String, Supplier> map) {
        analyzeBOQThreadPool = Executors.newFixedThreadPool(1);
        saveBOQThreadPool = Executors.newFixedThreadPool(1);
        messageCallBack.callBackMsg("开始解析工程量清单。");
        analyzeBOQThreadList.clear();
        successList.clear();
        failList.clear();
        messageCallBack.callBackMsg("正在删除历史清单数据...");
        long startTime = System.currentTimeMillis();
        int deleteCount = constructProjectService.deleteAllConstructProjectDetail(tenderProject.getId());
        System.out.println("删除 历史清标信息用时：" + DateUtils.timeSpan(System.currentTimeMillis()-startTime ));
        messageCallBack.callBackMsg("已删除"+deleteCount+"条历史清单数据！");
        
        for (String appendixPath : map.keySet()) {
            Supplier supplier = map.get(appendixPath);
            String supplierMessage = supplier == null ? "招标文件" : supplier.getSupplierName();
            AnalyzeBOQListener analyzeBOQListener = getAnalyzeBOQListener(supplierMessage, saveBOQThreadPool);
            AnalyzeBOQThread thread = new AnalyzeBOQThread(tenderProject, supplier, appendixPath, analyzeBOQListener);
            analyzeBOQThreadPool.submit(thread);
            analyzeBOQThreadList.add(thread);
        }
        analyzeBOQThreadPool.shutdown();
        try {
            analyzeBOQThreadPool.awaitTermination(1, TimeUnit.HOURS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (null == thread) {
            clearAnalyzeBOQ();
            return;
        }
        saveBOQThreadPool.shutdown();
        try {
            saveBOQThreadPool.awaitTermination(1, TimeUnit.HOURS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (null == thread) {
            clearAnalyzeBOQ();
            return;
        }
        showMessageResult();
    }
    
    /**
     * @Description: 获取解析工程量清单接听
     * @author chenxw
     * @param supplierMessage
     * @param saveBOQThreadPool
     * @return
     */
    private AnalyzeBOQListener getAnalyzeBOQListener(final String supplierMessage, final ExecutorService saveBOQThreadPool) {
        return new AnalyzeBOQListener() {
            public void analyzeBefore() {
                messageCallBack.callBackMsg("正在解析[".concat(supplierMessage).concat("]清单文件..."));
            }
            
            public void saveBefore() {
                messageCallBack.callBackMsg("开始导入[".concat(supplierMessage).concat("]清单内容..."));
            }
            
            public void analyzeAfter(boolean isSuccess) {
                if (!isSuccess) {
                    failList.add(supplierMessage);
                }
                messageCallBack.callBackMsg(isSuccess, "[".concat(supplierMessage).concat("]清单文件解析").concat(isSuccess ? "成功！" : "失败！"));
            }
            
            public void saveAfter(boolean isSuccess) {
                if (isSuccess) {
                    successList.add(supplierMessage);
                } else {
                    failList.add(supplierMessage);
                }
                messageCallBack.callBackMsg(isSuccess, "[".concat(supplierMessage).concat("]清单内容导入").concat(isSuccess ? "成功！" : "失败！"));
            }
            
            public void save(final AnalyzeBOQThread thread) {
                saveBOQThreadPool.submit(new Runnable() {
                    public void run() {
                        thread.saveConstructProjectDetail();
                    }
                });
            }
        };
    }
    
    /**
     * @Description: 显示结果消息
     * @author chenxw
     */
    private void showMessageResult() {
        messageCallBack.callBackMsg("\r\n===============================\r\n解析工程量清单任务结束，其中：");
        if(notFoundList.size() > 0){
            messageCallBack.callBackMsg(notFoundList.size() + "份工程量清单文件不存在；");
        }
        if(successList.size() > 0){
            messageCallBack.callBackMsg(successList.size() + "份工程量清单导入成功；");
        }
        if(failList.size() > 0){
            messageCallBack.callBackMsg(failList.size() + "份工程量清单导入失败；");
        }
        if (notFoundList.size() > 0) {
            messageCallBack.callBackMsg("\r\n以下清单文件未找到：");
            for (String notFound : notFoundList) {
                messageCallBack.callBackMsg(false, notFound);
            }
        }
        if (successList.size() > 0) {
            messageCallBack.callBackMsg("\r\n以下清单文件导入成功：");
            for (String success : successList) {
                messageCallBack.callBackMsg(true, success);
            }
        }
        if (failList.size() > 0) {
            messageCallBack.callBackMsg("\r\n以下清单文件导入失败：");
            for (String fail : failList) {
                messageCallBack.callBackMsg(false, fail);
            }
        }
    }
    
    /**
     * @Description: 清空已解析工程量清单
     * @author chenxw
     */
    private void clearAnalyzeBOQ() {
        for (AnalyzeBOQThread callable : analyzeBOQThreadList) {
            callable.clearData();
        }
    }
    
    public void start() {
        thread = new Thread(this);
        thread.start();
    }
    
    public void stop() {
        thread = null;
        if(null != analyzeBOQThreadPool){
            analyzeBOQThreadPool.shutdownNow();
        }
        if(null != saveBOQThreadPool){
            saveBOQThreadPool.shutdownNow();
        }
        for (AnalyzeBOQThread callable : analyzeBOQThreadList) {
            callable.setCancel(true);
        }
    }
}
