/**
 * 
 */
package com.pcloud.book.book.biz.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Maps;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.biz.BookProductBiz;
import com.pcloud.book.book.biz.BookResourceBiz;
import com.pcloud.book.book.cache.BookResourceCache;
import com.pcloud.book.book.dao.BookResourceDao;
import com.pcloud.book.book.dto.BookDto;
import com.pcloud.book.book.dto.BookResourceDto;
import com.pcloud.book.book.entity.BookResource;
import com.pcloud.book.book.set.BookSet;
import com.pcloud.common.exceptions.BizException;
import com.pcloud.common.utils.ListUtils;

/**
 * @描述：
 * @作者：songx
 * @创建时间：2016年12月23日,下午3:59:36
 * @版本：1.0
 */
@Service("bookResourceBiz")
public class BookResourceBizImpl implements BookResourceBiz {

	/**
	 * 
	 */
	private static final Logger LOGGER = LoggerFactory.getLogger(BookResourceBizImpl.class);
	
	@Autowired
	private BookResourceDao bookResourceDao;
	
	@Autowired
	private BookProductBiz bookProductBiz;
	
	@Autowired
	private BookResourceCache bookResourceCache;

	@Autowired
	private BookSet bookSet;
	/**
	 * 创建书刊应用关联关系
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void create(BookResource bookResource) throws BizException {
		// 校验参数
		this.checkParam(bookResource);

		try {
			LOGGER.info("【书籍-资源-编辑】创建书刊资源关联,<START>.[bookResource]=" + bookResource.toString());
			bookResourceDao.insert(bookResource);
			LOGGER.info("【书籍-资源-编辑】创建书刊资源关联,<END>");
		}catch (DataIntegrityViolationException e) {
			LOGGER.error("【书籍-资源-编辑】创建书刊资源关联,已关联过" + e.getMessage());
			throw new BizException(BookBizException.FREQUENTLY_REQUEST, "请稍等，正在处理中...");
		}catch (Exception e) {
			LOGGER.error("【书籍-资源-编辑】创建书刊资源关联,<ERROR>.[bookDao.insert]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "创建书刊资源关联失败~！");
		}
		//清除缓存
		bookResourceCache.clearBookResourceCache(bookResource.getBookId(), bookResource.getChannelId(), bookResource.getCreatedUser());
	}

	/**
	 * 检验参数
	 */
	private void checkParam(BookResource bookResource) throws BizException {
		if (bookResource.getBookId() == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书刊");
		}
		if (bookResource.getResourceId() == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择资源");
		}
		if (bookResource.getChannelId() == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择运营平台");
		}
	}
	
	/**
	 * 删除书刊应用关联
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void delete(Long bookResourceId) throws BizException {
		LOGGER.info("【书籍-资源-编辑】删除书刊资源关联,<START>.[bookResourceId]=" + bookResourceId);
		if (bookResourceId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择资源");
		}
		//清除缓存
		bookResourceCache.clearByBookResourceId(bookResourceId);
		
		try {
			bookResourceDao.deleteById(bookResourceId);
			LOGGER.info("【书籍-资源-编辑】删除书刊资源关联,<END>");
		} catch (Exception e) {
			LOGGER.error("【书籍-资源-编辑】删除书刊资源关联,<ERROR>.[bookResourceDto.deleteById]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "删除书刊资源关联失败~！");
		}
		
	}
	
	/**
	 * 根据书籍删除关联的资源
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteByBook(Long bookId) throws BizException {
		LOGGER.info("【书籍-资源-编辑】根据书籍删除关联的应用,<START>.[bookId]=" + bookId);
		if (bookId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书籍");
		}

		try {
			bookResourceDao.deleteByBook(bookId);
			LOGGER.info("【书籍-资源-编辑】根据书籍删除关联的应用,<END>");
		} catch (Exception e) {
			LOGGER.error("【书籍-资源-编辑】根据书籍删除关联的应用,<ERROR>.[bookResourceDto.deleteByBook]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "根据书籍删除关联的应用~！");
		}
		//清除缓存
		try{
			bookResourceCache.clearBookCache(bookId);
		}catch(Exception e){
			LOGGER.error("清除图书资源缓存失败失败bookId"+bookId);
		}
		
	}
	
	/**
	 * 批量删除资源关联关系
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteByBooks(List<Long> bookIds) throws BizException {
		LOGGER.info("【书籍-资源-编辑】批量删除资源关联关系,<START>.[bookIds]=" + bookIds.toString());
		if (bookIds == null || bookIds.isEmpty()) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识不能为空~！");
		}

		try {
			bookResourceDao.deleteByBooks(bookIds);
			LOGGER.info("【书籍-资源-编辑】批量删除资源关联关系,<END>");
		} catch (Exception e) {
			LOGGER.error("【书籍-资源-编辑】批量删除资源关联关系,<ERROR>.[bookResourceDto.deleteByBooks]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "批量删除应用关联关系失败~！");
		}
		try{
			//批量删除资源关联
			for(Long bookId:bookIds){
				bookResourceCache.clearBookCache(bookId);
			}	
		}catch(Exception e){
			LOGGER.error("清除图书资源缓存失败bookIds"+bookIds);
		}
		
	}
	
	/**
	 * 获取书籍关联的资源
	 */
	@Override
	public List<BookResourceDto> getListById(Long bookId, Long adviserId, Long channelId) throws BizException {
		LOGGER.info("【书籍-资源-编辑】获取书籍关联的资源,<PARAM>.[bookId]=" + bookId+"adviserId="+adviserId+"channelId="+channelId);
		List<BookResourceDto> bookResource = listBaseById(bookId,adviserId,channelId);
		bookSet.setResourceInfo(bookResource);
		return bookResource;
	}
	
	/**
	 * 获取书籍关联的资源
	 */
	@Override
	public List<BookResourceDto> listBaseById(Long bookId, Long adviserId, Long channelId) throws BizException {
		LOGGER.info("【书籍-资源-编辑】获取书籍关联的资源,<PARAM>.[bookId]=" + bookId+"adviserId="+adviserId+"channelId="+channelId);
		if (bookId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识不能为空~！");
		}
		if (adviserId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "顾问标识不能为空~！");
		}
		if (channelId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "渠道标识不能为空~！");
		}
		
		try {
			List<BookResourceDto> bookResources = bookResourceCache.listBookResource(bookId, channelId, adviserId);
			if(ListUtils.isEmpty(bookResources)){
				BookResource bookResource = new BookResource();
				bookResource.setBookId(bookId);
				bookResource.setChannelId(channelId);
				bookResource.setCreatedUser(adviserId);
				bookResources = bookResourceDao.getListById(bookResource);
			}
			
			if (bookResources == null) {
				bookResources = new ArrayList<>();
			}else{
				bookResourceCache.setBookResourceAssoc(bookId, channelId, adviserId, bookResources);
			}
			LOGGER.info("【书籍-资源-编辑】获取书籍关联的资源,<END>.[bookResources]=" + bookResources.toString());
			return bookResources;
		} catch (Exception e) {
			LOGGER.error("【书籍-资源-编辑】获取书籍关联的资源,<ERROR>.[bookResourceDto.getListById]:" + e.getMessage(), e);
			throw BizException.DB_SELECT_IS_FAIL;
		}
	}
	
	
	/**
	 * 获取书籍关联的资源文件（加入文章）
	 */
	public List<Object> listResourceFileById(Long bookId, Long adviserId, Long channelId) throws BizException {
		// 从缓存中获取图书与资源关联
		List<BookResourceDto> bookResources = listBaseById(bookId, adviserId, channelId);
		//设置资源关联资源文件（包含文章资源）
		return bookSet.listResourceFile(bookResources);
		
	}
	
	/**
	 * 根据书籍和渠道删除书籍资源关联信息
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteByBookAndChannel(Long bookId, Long channelId) throws BizException {
		LOGGER.info("【编辑书刊】根据书籍和渠道删除书籍资源关联信息,<START>.[bookId]=" + bookId+",[channelId]=" + channelId);
		try {
			Map<String, Object> paramMap = Maps.newHashMap();
			paramMap.put("bookId", bookId);
			paramMap.put("channelId", channelId);
			bookResourceDao.deleteByBookAndChannel(paramMap);
		} catch (Exception e) {
			LOGGER.error("【编辑书刊】根据书籍和渠道删除书籍资源关联信息,<ERROR>.[deleteByBookAndChannel]:" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "根据书籍和渠道删除书籍资源关联信息失败");
		}
	}

	/**
	 * 获取书籍关联作品与应用
	 */
	@Override
	public BookDto getResouceByBook(Long bookId, Long adviserId, Long channelId) {
		BookDto bookDto = new BookDto();
		// 填充书籍关联的作品
		bookDto.setProducts(bookProductBiz.getProListById(bookId, adviserId, channelId));
		// 填充书籍配套资源
//		bookDto.setResourceFiles(bookSet.setResourceFile(getListById(bookId, adviserId, channelId)));
		bookDto.setResourceFiles(listResourceFileById(bookId, adviserId, channelId));
		return bookDto;
	}

	/**
	 * 获取图书关联资源个数
	 */
	@Override
	public Integer getResourceCount(Long adviserId, Long bookId, Long channelId) {
		LOGGER.info("【编辑书刊】获取图书关联资源个数,<START>.[bookId]=" + bookId+",[channelId]=" + channelId+"[adviserId]="+adviserId);
		try {
			Map<String, Object> paramMap = Maps.newHashMap();
			paramMap.put("bookId", bookId);
			paramMap.put("channelId", channelId);
			paramMap.put("adviserId", adviserId);
			return bookResourceDao.getResourceCount(paramMap);
		} catch (Exception e) {
			LOGGER.error("【编辑书刊】获取图书关联资源个数,<ERROR>.[getResourceCount]:" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "获取图书关联资源个数失败");
		}
	}

	/**
	 * 获取图书关联资源文件
	 */
	@Override
	public List<BookResourceDto> listById4Agent(Long bookId, Long adviserId, Long channelId) throws BizException {
		// 从缓存中获取图书与资源关联
		List<BookResourceDto> bookResources = listBaseById(bookId, adviserId, channelId);
		//设置资源基本信息
		bookSet.setResourceInfo(bookResources);
		return bookResources;
	}

	/**
	 * 获取资源关联的图书
	 */
	@Override
	public List<Long> listByResourceId(Long resourceId) {
		LOGGER.info("获取资源关联的图书 resourceId="+resourceId);
		List<Long> bookIds = bookResourceDao.listByResourceId(resourceId);
		return bookIds;
	}
}
