package com.starcharge.component.datastore.fileio;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.aliyun.oss.OSSClientBuilder;
import com.ihidea.core.support.exception.ServiceException;
import com.ihidea.core.util.JSONUtilsEx;
import com.starcharge.component.datastore.DataStoreService;
import com.starcharge.component.datastore.dao.CptDataInfoMapper;
import com.starcharge.component.datastore.dao.model.CptDataInfo;
import com.starcharge.component.datastore.dao.model.CptDataStore;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import com.aliyun.oss.OSS;
import com.aliyun.oss.model.CopyObjectRequest;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;

/**
 * 阿里云存储对象OSS
 * @author wenhao
 */
@Component
@Lazy
public class FileIoOSS implements IFileIo {

	private static Map<String, Map<String, String>> bucketMap = new HashMap<String, Map<String, String>>();
	
	private static OSS ossClient = null;
	
	@Autowired
	private DataStoreService dataStoreService;

	@Autowired
	private CptDataInfoMapper dataInfoDao;

	@SuppressWarnings("unchecked")
	private synchronized Map<String, String> initBucketInfo(String storeName) {

		CptDataStore cptDataStore = dataStoreService.getInfoByName(storeName);
		Map<String, String> bucketInfo = JSONUtilsEx.deserialize(cptDataStore.getPath(), Map.class);
		bucketMap.put(storeName, bucketInfo);

		return bucketInfo;
	}
	
	private synchronized void initOssClient(Map<String, String> bucketInfo) {
//		ossClient = new OSSClient(bucketInfo.get("endpoint"), bucketInfo.get("accessKeyId"), bucketInfo.get("accessKeySecret"));
		ossClient = new OSSClientBuilder().build(bucketInfo.get("endpoint"), bucketInfo.get("accessKeyId"), bucketInfo.get("accessKeySecret"));
	}

	public Map<String, String> getBucketInfo(String storeName){
		Map<String, String> bucketInfo = bucketMap.get(storeName);

		// 根据storeName得到参数
		if (bucketInfo == null) {
			bucketInfo = initBucketInfo(storeName);
		}
		
		if(ossClient == null){
			initOssClient(bucketInfo);
		}
		
		return bucketInfo;
	}
	
	/**
	 * 保存到OSS
	 */
	@Override
	public void save(FileIoEntity entity) {
		String id= StringUtils.isNotBlank(entity.getDataInfo().getPrefix()) ? entity.getDataInfo().getPrefix()+"/"+entity.getDataInfo().getId() : entity.getDataInfo().getId();
		saveFile(id, entity.getDataInfo().getFileName(), entity.getContent(), entity.getDataInfo().getStoreName());
	}

	/**
	 * 保存到备份存储OSS
	 */
	public void saveBak(FileIoEntity entity) {
		throw new ServiceException("未实现");
	}


	private void saveFile(String id, String name, byte[] content, String storeName) {

		try{
			Map<String, String> bucketInfo = getBucketInfo(storeName);
			
			ossClient.putObject(bucketInfo.get("bucketName"), bucketInfo.get("key") + id, new ByteArrayInputStream(content));
		}catch (Exception e) {
			throw new ServiceException("阿里云存储对象OSS上传出现异常:" + e.getMessage(), e);
		}
		
	}

	@Override
	public boolean remove(FileIoEntity entity) {
		throw new ServiceException("未实现");
	}

	public byte[] get(String id) {
		
		byte[] data = null;
		
		CptDataInfo dataInfo = dataInfoDao.selectByPrimaryKey(id);
		if(dataInfo != null){
			Map<String, String> bucketInfo = getBucketInfo(dataInfo.getStoreName());
			
			OSSObject ossObject = ossClient.getObject(bucketInfo.get("bucketName"),  bucketInfo.get("key") + id);
			
	        try {
	        	InputStream inputStream = ossObject.getObjectContent();
				data=toByteArray(inputStream);
				inputStream.close();
			} catch (IOException e) {
				throw new ServiceException("阿里云存储对象OSS获得对象出现异常:" + e.getMessage());
			}
		}
		return data;
	}

	@Override
	public void execute(FileIoEntity fileIoEntity, IFileInputStream fileInputStreamImpl) throws Exception {
		throw new ServiceException("未实现");
	}

	@Override
	public void updateContent(String id, byte[] content) {
		throw new ServiceException("未实现");
	}
	
	private static byte[] toByteArray(InputStream in) throws IOException {
        ByteArrayOutputStream out=new ByteArrayOutputStream();
        byte[] buffer=new byte[1024*4];
        int n=0;
        while ( (n=in.read(buffer)) !=-1) {
            out.write(buffer,0,n);
        }
        return out.toByteArray();
    }
	
	public void deleteFile(String id, String storeName, String prefix) {
		try{
			Map<String, String> bucketInfo = getBucketInfo(storeName);
			
			ossClient.deleteObject(bucketInfo.get("bucketName"), bucketInfo.get("key") +(StringUtils.isNotBlank(prefix) ? prefix+"/"+id : id));
		}catch (Exception e) {
			throw new ServiceException("阿里云OSS批量删除文件出现异常:" + e.getMessage(), e);
		}
	}
	
	public void deleteFileBatch(List<String> idList, String storeName, String prefix) {
		try{
			Map<String, String> bucketInfo = getBucketInfo(storeName);
			
			List<String> keys=new ArrayList<>();
			for (String id : idList) {
				keys.add(bucketInfo.get("key") + (StringUtils.isNotBlank(prefix) ? prefix+"/"+id : id));
			}
			
			DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketInfo.get("bucketName")).withKeys(keys));
			List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
			System.out.println("成功删除:"+deletedObjects.toString());
			
		}catch (Exception e) {
			throw new ServiceException("阿里云OSS批量删除文件出现异常:" + e.getMessage(), e);
		}
	}
	
	public void copyFile(String sourceFileName, String destFileName, String storeName) {
		try{
			Map<String, String> bucketInfo = getBucketInfo(storeName);
			
			CopyObjectRequest copyObjectRequest = new CopyObjectRequest(bucketInfo.get("bucketName"), bucketInfo.get("key") + sourceFileName, bucketInfo.get("bucketName"), bucketInfo.get("key") +destFileName);

			ossClient.copyObject(copyObjectRequest);
		}catch (Exception e) {
			throw new ServiceException("阿里云OSS复制文件出现异常:" + e.getMessage(), e);
		}
	}
	
	public boolean exist(String id, String storeName, String prefix) {
		try{
			Map<String, String> bucketInfo = getBucketInfo(storeName);
			

			return ossClient.doesObjectExist(bucketInfo.get("bucketName"), bucketInfo.get("key") + (StringUtils.isNotBlank(prefix) ? prefix+"/"+id : id));
		}catch (Exception e) {
			throw new ServiceException("阿里云检查文件是否存在出现异常:" + e.getMessage(), e);
		}
	}
	
	/**
	 * 获取文件列表,最多100个
	 * @param prefix
	 * @param storeName
	 * @return
	 */
	public List<String> list(String prefix, String storeName) {
		try{
			Map<String, String> bucketInfo = getBucketInfo(storeName);
			
			ObjectListing objectListing = ossClient.listObjects(bucketInfo.get("bucketName"), bucketInfo.get("key")+prefix);
			
			List<String> fileIdList=new ArrayList<>();
			List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
			for (OSSObjectSummary s : sums) {
				fileIdList.add(s.getKey());
			}
			return fileIdList;
		}catch (Exception e) {
			throw new ServiceException("阿里云列举文件出现异常:" + e.getMessage(), e);
		}
	}
	
	
	public static void main(String[] args) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("endpoint", "oss-cn-qingdao.aliyuncs.com");
		map.put("key", "img/");
		
		System.out.println(JSONUtilsEx.serialize(map));
	}
	
}