package com.wisedu.mooc.app.platform.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.wisedu.coeus.core.ConstantStatic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wisedu.coeus.debug.Logger;
import com.wisedu.coeus.debug.LoggerFactory;
import com.wisedu.coeus.util.FileUtils;
import com.wisedu.coeus.util.Strings;
import com.wisedu.mooc.app.platform.bo.Unit;
import com.wisedu.mooc.app.platform.bo.UnitItem;
import com.wisedu.mooc.app.platform.dao.UnitItemDao;
import com.wisedu.mooc.app.platform.service.UnitItemService;
import com.wisedu.mooc.app.study.bo.UserStudy;
import com.wisedu.mooc.app.study.service.UserStudyService;
import com.wisedu.mooc.app.thirdparty.service.ThirdpartyInstance;
import com.wisedu.mooc.app.thirdparty.service.ThirdpartyService;
import com.wisedu.mooc.app.upload.RsConstant;
import com.wisedu.mooc.app.upload.exception.UploadException;
import com.wisedu.mooc.app.upload.service.UploadFactory;
import com.wisedu.mooc.app.upload.service.UploadService;
import com.wisedu.mooc.app.upload.vo.UploadVo;

@Service("unitItemService")
public class UnitItemServiceImpl implements UnitItemService {
	
	private static final Logger log = LoggerFactory.getLogger(UnitItemServiceImpl.class);
	
	private static final Semaphore JOB_SEMAPHORE = new Semaphore(1);
    private static final ThreadPoolExecutor JOB_EXECUTOR = new ThreadPoolExecutor(10, 20, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(100000), new ThreadPoolExecutor.CallerRunsPolicy());
	
	@Autowired
	private UnitItemDao unitItemDao;
	@Autowired
	private UserStudyService userStudyService;

	private UploadService uploadService;
	
	public UploadService getUploadService() {
        if (uploadService == null) {
            uploadService = UploadFactory.getInstance(RsConstant.NODES_PATH);
        }
        return uploadService;
    }
	
	@Override
	public List<UnitItem> queryItemList(Long unitId) {
		return this.unitItemDao.queryItemList(unitId);
	}

	@Override
	public List<Unit> queryUnitList() {
		return this.unitItemDao.queryUnitList();
	}

	public Unit queryUnitById(Long unitId){
		return this.unitItemDao.queryUnitById(unitId);
	}
	
	public UnitItem queryUnitItemById(Long itemId){
		return this.unitItemDao.queryUnitItem(itemId);
	}

	@Override
	public void saveOrUpdateItem(Long unitId, Long itemId,String videoRelativePath, 
			String videoTempPath,String thumbRelativePath, String thumbTempPath,
			String currentVideoPath, String currentThumbPath,String videoFileName) {
        try {
        	UnitItem unitItem = null;
            if (itemId == 0) {    //新增
            	unitItem = new UnitItem();
            	unitItem.setDeleteFlag(0);
            	unitItem.setUnitId(unitId);
            	unitItem.setItemName(videoFileName);
            	unitItem.setVideoName(videoFileName);
            	
                if (Strings.isNotEmpty(videoRelativePath)) {
                	unitItem = initVideoItem(unitItem,videoRelativePath,videoTempPath);
                }
                
                if (Strings.isNotEmpty(thumbRelativePath)) {
                	unitItem.setVideoPic(thumbRelativePath);
                	moveFile(thumbRelativePath,thumbTempPath);
                }
                
                Integer displayOrder = this.unitItemDao.queryMaxDisplayOrder(unitId);
                if(null == displayOrder || 0 == displayOrder){
                	displayOrder = 1;
                }
                unitItem.setDisplayOrder(displayOrder);
                this.unitItemDao.saveUnitItem(unitItem);
                doUploadFile(unitItem.getItemId());
            } else {
            	unitItem = this.unitItemDao.queryUnitItem(itemId);
            	unitItem.setVideoName(videoFileName);
            	
            	if (Strings.isNotEmpty(videoRelativePath)) {
            		unitItem = initVideoItem(unitItem,videoRelativePath,videoTempPath);
            		doUploadFile(unitItem.getItemId());
                }
            	
            	if (Strings.isNotEmpty(thumbRelativePath)) {
            		unitItem.setVideoPic(thumbRelativePath);
            		moveFile(thumbRelativePath,thumbTempPath);
                } else {
                    if (Strings.isEmpty(currentThumbPath)) {
                    	unitItem.setVideoPic(null);
                    }
                }
                this.unitItemDao.updateUnitItem(unitItem);
            }
        } catch (Exception e) {
        	log.debug(e.getMessage(), e);
        }
	}
	
	private UnitItem initVideoItem(UnitItem unitItem,String videoRelativePath,String videoTempPath){
    		unitItem.setVideoUrl(videoRelativePath);
    		unitItem.setDuration(FileUtils.getVideoDuration(videoTempPath));
    		if(ConstantStatic.UPLOAD_RESOURCE_TYPE.equals(ConstantStatic.UPLOAD_RESOURCE_TYPE_LOCAL)){
    			unitItem.setVideoFlvUrl(videoRelativePath);
    		}
    		moveFile(videoRelativePath,videoTempPath);
    		return unitItem;
    		
	}
	
	@Override
    public List<Map<String, Object>> queryStudyUnit(Long userId) {
        List<Map<String,Object>> list = new ArrayList<Map<String, Object>>();
        List<UserStudy> usList = this.userStudyService.queryUserStudyRecord(userId);
        Map<Long, UserStudy> studyMap = new HashMap<Long, UserStudy>();
    	for (UserStudy us : usList){
    		studyMap.put(us.getItemId(), us);
    	}
        List<Unit> unitList = this.unitItemDao.queryUnitList();
        Unit unit = null;
        Map<String,Object> map = null;
        boolean isLock = false;
        for (int j=0;j<unitList.size();j++){
            map = new HashMap<String, Object>();
            unit = unitList.get(j);
            map.put("unit",unit);
            map.put("isLock",isLock);
            boolean isOver = true;
            if (!isLock){//如果一个被锁定后面的内容全部锁定
            	List<UnitItem> items = this.unitItemDao.queryItemList(unit.getUnitId());
                //isLock = false;
                for (UnitItem item : items){
                	UserStudy study = studyMap.get(item.getItemId());
                	if (study==null||study.getIsOver()!=UserStudy.IS_OVER_YES){
                		isOver = false;
                		isLock = true;
                	}
                }
            }
            map.put("isOver", isOver);
            list.add(map);
        }
        return list;
    }

	public void moveFile(String relativePath,String tempPath){
		if(Strings.isEmpty(relativePath) || Strings.isEmpty(tempPath)){
			log.error("ERROR MOVE FILE ,relativePath:"+relativePath+",tempPath:"+tempPath);
			return ;
		}
		UploadVo uploadVo = new UploadVo();
        uploadVo.setFileAbsolutePath(relativePath);
        uploadVo.setFileRelativePath(relativePath);
        uploadVo.setFileTempPath(tempPath);
        try {
            getUploadService().uploadEndOperate(uploadVo);
        } catch (UploadException e) {
            log.error("ERROR MOVE FILE" + e.getErrorCode() + uploadVo.getFileTempPath());
        }
	}


    @Override
    public void insertUnit(Unit unit) {
        Integer maxOrder = this.unitItemDao.queryMaxOrder();
        unit.setDisplayOrder(maxOrder+1);
        this.unitItemDao.insert(unit);
    }

    @Override
    public void deleteItem(Long itemId) {
        UnitItem item = this.unitItemDao.queryUnitItem(itemId);
        if (Strings.isNotEmpty(item)){
            item.setDeleteFlag(ConstantStatic.INT_1);
            this.unitItemDao.update(item);
        }
    }

    @Override
    public void deleteUnit(Long unitId) {
        Unit unit = this.unitItemDao.queryUnitById(unitId);
        if (Strings.isNotEmpty(unit)){
            unit.setDeleteFlag(ConstantStatic.INT_1);
            this.unitItemDao.update(unit);
        }
    }

    @Override
    public void updateUnit(Long unitId, Unit newUnit) {
        Unit unit = this.unitItemDao.queryUnitById(unitId);
        if (Strings.isNotEmpty(unit)){
            unit.setUnitNo(newUnit.getUnitNo());
            unit.setUnitName(newUnit.getUnitName());
            this.unitItemDao.update(unit);
        }
    }
    
    public void doUploadFile(final Long itemId){
    	 Runnable run = new Runnable() {
             public void run() {
                 try {
                     // 获取许可
                     JOB_SEMAPHORE.acquire();
                     /**睡眠10秒钟 确保 UnitItem 创建并插入到数据库成功完成 **/
                     Thread.sleep(10000);
                     ThirdpartyService thirdpartyService = ThirdpartyInstance.getThirdpartyService();
                     thirdpartyService.doUpload(itemId);

                 }catch (Exception e) {
                	 log.error(e.getMessage(), e);
                 } finally {
                     // 访问完后，释放
                     JOB_SEMAPHORE.release();
                 }
             }
         };
         JOB_EXECUTOR.execute(run);
    }
    
    @Override
    public void updateUnitSort(String unitIds, String displayOrders) {
        String[] strUnitId = unitIds.split(",");
        String[] strDisplayOrder = displayOrders.split(",");
        List<Long> unitIdList = new ArrayList<Long>();
        for (int i=0;i<strUnitId.length;i++){
            unitIdList.add(Strings.getLong(strUnitId[i]));
        }
        List<Unit> updateUnitList = new ArrayList<Unit>();
        List<Unit> unitList = this.unitItemDao.queryUnitListById(unitIdList);
        if (unitList!=null && unitList.size()>0){
            for (int a=0;a<strUnitId.length;a++){
                Integer displayOrder = Strings.getInteger(strDisplayOrder[a]);
                for (int j=0;j<unitList.size();j++){
                    Unit unit = unitList.get(j);
                    if (unit.getUnitId().equals(Strings.getLong(strUnitId[a]))){
                        unit.setDisplayOrder(displayOrder);
                        updateUnitList.add(unit);
                        break;
                    }
                }
            }
            if (updateUnitList!=null && updateUnitList.size()>0){
                this.unitItemDao.updateAll(updateUnitList);
            }
        }
    }


    @Override
    public void updateItemSort(Long unitId, Long itemId, String itemChildIds, String displayOrders) {
        List<UnitItem> updateItemList = new ArrayList<UnitItem>();
        String[] strItemChildId = itemChildIds.split(",");
        String[] strDisplayOrder = displayOrders.split(",");
        List<Long> itemIdList = new ArrayList<Long>();
        for (int i=0;i<strItemChildId.length;i++){
            itemIdList.add(Strings.getLong(strItemChildId[i]));
        }
        List<UnitItem> itemList = this.unitItemDao.queryItemListById(itemIdList);
        for (int a=0;a<strItemChildId.length;a++){
            Long itemIds = Strings.getLong(strItemChildId[a]);
            Integer displayOrder = Strings.getInteger(strDisplayOrder[a]);
            for (int j=0;j<itemList.size();j++){
                UnitItem unitItem = itemList.get(j);
                if (unitItem.getItemId().equals(itemIds)){
                    unitItem.setDisplayOrder(displayOrder);
                    unitItem.setUnitId(unitId);
                    updateItemList.add(unitItem);
                    break;
                }
            }
        }
        if (updateItemList!=null && updateItemList.size()>0){
            this.unitItemDao.updateAll(updateItemList);
        }
    }

    @Override
    public void updateItem(Long itemId, String itemName) {
        UnitItem item = this.unitItemDao.queryUnitItem(itemId);
        if (Strings.isNotEmpty(item)){
            item.setItemName(itemName);
            this.unitItemDao.update(item);
        }
    }
    
    @Override
    public void updateItem(UnitItem item) {
        if (Strings.isNotEmpty(item)){
            this.unitItemDao.update(item);
        }
    }
}
    
