package com.house365.commons.system;

import com.google.common.base.Joiner;
import com.house365.web.util.MemoryPropertyPlaceholderConfigurer;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * FastDFS文件操作工具类
 *
 * @author bvnb
 * @version [v1.0.0, 2015年1月24日]
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
public final class FastDFSUtil {

    private static final Logger logger = LoggerFactory.getLogger(FastDFSUtil.class);

    private static final String EMPTY = "";

    private static TrackerClient trackerClient;
    private static TrackerServer trackerServer;
    private static StorageServer storageServer;
    private static StorageClient storageClient;
    //文件URL通用前缀
    private static String fileUrlPrefix;
    //服务器环境：生产环境production或测试环境test
    private static String env;

    static {
        try {
            //从配置文件中获取
            fileUrlPrefix = MemoryPropertyPlaceholderConfigurer.getContextProperty("system.default.fileServer");
            env = MemoryPropertyPlaceholderConfigurer.getContextProperty("system.env");
            String classPath = new File(FastDFSUtil.class.getResource("/").getFile()).getCanonicalPath();
            String fdfsConf = "/fdfs_client.conf";
            if ("production".equalsIgnoreCase(env)) {
                fdfsConf = "/fdfs_client_" + env + ".conf";
            }
            String configFilePath = classPath + fdfsConf;
            logger.debug("配置文件:" + configFilePath);
            ClientGlobal.init(configFilePath);
            trackerClient = new TrackerClient();
            trackerServer = trackerClient.getConnection();
            storageClient = new StorageClient(trackerServer, storageServer);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传本地文件
     *
     * @param localFilename 本地文件绝对路径
     * @return 可访问的文件URL；<br>
     * return <b>""</b> if fail
     */
    public static String uploadFile(String localFilename) {
        String fileUrl = EMPTY;
        List<String> result = uploadFileAndGetAll(localFilename);
        int indexOfFileUlr = 2; // 文件 URL 在结果数组中的索引
        if (CollectionUtils.isNotEmpty(result) && result.size() > indexOfFileUlr) {
            fileUrl = result.get(indexOfFileUlr);
        }
        return fileUrl;
    }

    /**
     * 上传本地文件，返回 FastDFS 文件信息
     *
     * @param localFilename 本地文件绝对路径
     * @return 3 elements string list if success:<br>
     * <ul><li>results[0]: the group name to store the file </li></ul>
     * <ul><li>results[1]: the new created filename</li></ul>
     * <ul><li>results[2]: the new created file url</li></ul>
     * return <b>empty list</b> if fail
     */
    public static List<String> uploadFileAndGetAll(String localFilename) {
        File file = new File(localFilename);
        if (!file.exists() || !file.isFile()) {
            logger.error("当前文件不存在或不是文件，上传失败");
            return null;
        }
        List<String> list = new ArrayList<String>();
        String[] results = new String[3];
        String fileUrl = EMPTY;
        String fileExt = getFileSuffix(localFilename);
        try {
            NameValuePair[] metaList = new NameValuePair[3];
            metaList[0] = new NameValuePair("fileName", file.getName());
            metaList[1] = new NameValuePair("fileExt", fileExt);
            metaList[2] = new NameValuePair("fileLength", EMPTY + file.length());
            logger.info("*******************metaList[0]*************************" + metaList[0]);
            logger.info("*******************metaList[1]*************************" + metaList[1]);
            logger.info("*******************metaList[2]*************************" + metaList[2]);
            results = storageClient.upload_file(localFilename, fileExt, metaList);

            if ("production".equalsIgnoreCase(env)) {
                fileUrlPrefix = MemoryPropertyPlaceholderConfigurer.getContextProperty("fastdfs.storage." + results[0]);
            }
            fileUrl = fileUrlPrefix + results[1];
            list.add(results[0]);
            list.add(results[1]);
            list.add(fileUrl);
            logger.debug("groupName：" + results[0] + ",remoteFilename：" + results[1]);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 以流的方式上传文件
     *
     * @param inStream
     * @param uploadFileName
     * @return 可访问的文件URL
     * @throws IOException
     */
    public static String uploadFileByStream(InputStream inStream, String uploadFileName) throws IOException {
        byte[] fileBuffer = new byte[inStream.available()];
        inStream.read(fileBuffer);

        return uploadFileByByteArray(fileBuffer, uploadFileName);
    }

    /**
     * 以字节数组的方式上传文件
     *
     * @param fileBuffer
     * @param uploadFileName
     * @return 可访问的文件URL
     * @throws IOException
     */
    public static String uploadFileByByteArray(byte[] fileBuffer, String uploadFileName) throws IOException {
        String fileExtName = EMPTY;
        if (uploadFileName.contains(".")) {
            fileExtName = getFileSuffix(uploadFileName);
        } else {
            logger.error("Fail to upload file, because the format of filename is illegal.");
            return EMPTY;
        }
        NameValuePair[] metaList = new NameValuePair[3];
        metaList[0] = new NameValuePair("fileName", uploadFileName);
        metaList[1] = new NameValuePair("fileExtName", fileExtName);
        metaList[2] = new NameValuePair("fileLength", String.valueOf(fileBuffer.length));
        String remoteFilename = EMPTY;
        try {
            // results[0]: groupName, results[1]: remoteFilename.
            logger.info("=fileBuffer===" + fileBuffer + "==fileExtName=" + fileExtName + "==metaList==" + metaList);
            String[] results = storageClient.upload_file(fileBuffer, fileExtName, metaList);

            if ("production".equalsIgnoreCase(env)) {
                fileUrlPrefix = MemoryPropertyPlaceholderConfigurer.getContextProperty("fastdfs.storage." + results[0]);
            }
            //根据group 切换图片域名
            logger.info("=fileUrlPrefix===" + fileUrlPrefix + "==results[0]=" + results[0] + "==results[1]=" + results[1] );
            logger.info("*******************results*************************" + Joiner.on(",").join(results));
            remoteFilename = fileUrlPrefix + results[1];
            logger.info("**************remoteFilename************************" + remoteFilename);
        } catch (MyException e) {
            logger.error(e.getMessage() + "Upload file " + uploadFileName + " fails", e);
        }

        return remoteFilename;
    }

    /**
     * 获取文件后缀名，不含.
     *
     * @param fileName
     * @return 文件后缀
     */
    public static String getFileSuffix(String fileName) {
        String suffix = EMPTY;
        if (!StringUtils.isBlank(fileName)) {
            suffix = fileName.substring(fileName.lastIndexOf('.') + 1);
        }
        return suffix;
    }

    /**
     * 从 storage server 删除指定文件，返回 0 表示删除成功
     *
     * @param remote_filename
     * @return 0 for success, none zero for fail (error code)
     */
    public static int deleteFile(String remote_filename, String group_name) throws IOException, MyException {
        int result = storageClient.delete_file(group_name, remote_filename);
        return result;
    }

}
