package com.house365.common;

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 org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

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 [产品/模块版本] （可选）
 */

@Component
@ConfigurationProperties(prefix = "file")
public final class FastDFSUtil {

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

    private final String EMPTY = "";

    private TrackerClient trackerClient;
    private TrackerServer trackerServer;
    private StorageServer storageServer;
    private StorageClient storageClient;
    private String fileServer;

    private String env;

    private String group1;

    private String group2;

    private String group3;

    private String group4;

    private String group5;

    private String group6;

    private String group7;

    private String group8;

    private String group9;


    private String path;

    private void init() {
        try {
            //从配置文件中获取
            String fdfsConf = new File(
                    FastDFSUtil.class.getResource("/").getFile()).getCanonicalPath() + "/fdfs_client.conf";
            if ("production".equalsIgnoreCase(env)) {
                fdfsConf = File.separator + "database" + File.separator + "spring-cloud" + File.separator + "wechat" + File.separator + "fdfs_client_" + env + ".conf";
            } else {
//                fdfsConf = File.separator + "database" + File.separator + "spring-cloud" + File.separator + "wechattest" + File.separator + "fdfs_client" + ".conf";
                fdfsConf = getPath();
            }
            String configFilePath = fdfsConf;
            logger.debug("配置文件:" + configFilePath);
            ClientGlobal.init(configFilePath);
            trackerClient = new TrackerClient();
            trackerServer = trackerClient.getConnection();
            storageClient = new StorageClient(trackerServer, storageServer);
            ProtoCommon.activeTest(trackerServer.getSocket());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传本地文件
     *
     * @param localFilename 本地文件绝对路径
     * @return 可访问的文件URL；<br>
     * return <b>""</b> if fail
     */
    public 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 List<String> uploadFileAndGetAll(String localFilename) {
        if (storageClient == null) {
            init();
        }

        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());
            results = storageClient.upload_file(localFilename, fileExt, metaList);
            System.out.println("---------------------------------返回地址:"+results[0]);
            System.out.println("---------------------------------环境:"+env);
            System.out.println("---------------------------------fileServer:"+fileServer);
            if ("production".equalsIgnoreCase(env)) {
                if ("group1".equals(results[0])) {
                    fileServer = group1;
                } else if ("group2".equals(results[0])) {
                    fileServer = group2;
                }else if ("group3".equals(results[0])) {
                    fileServer = "http://img35.house365.com/";
                }else if ("group4".equals(results[0])) {
                    fileServer = "http://img37.house365.com/";
                }else if ("group5".equals(results[0])) {
                    fileServer = "http://img39.house365.com/";
                }else if ("group6".equals(results[0])) {
                    fileServer = "http://img41.house365.com/";
                }else if ("group7".equals(results[0])) {
                    fileServer = "http://img43.house365.com/";
                }else if ("group8".equals(results[0])) {
                    fileServer = "http://img45.house365.com/";
                }else if ("group9".equals(results[0])) {
                    fileServer = "http://img47.house365.com/";
                }
            }
            System.out.println("---------------------------------fileServer2:"+fileServer);
            System.out.println("---------------------------------results[1]:"+results[1]);
            fileUrl = fileServer + 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 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 String uploadFileByByteArray(byte[] fileBuffer, String uploadFileName) throws IOException {
        if (storageClient == null) {
            init();
        }

        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.
            String[] results = storageClient.upload_file(fileBuffer, fileExtName, metaList);
            logger.debug("====>>env:{}==results[0]:{}>>======", env, results[0]);
            if ("production".equalsIgnoreCase(env)) {
                if ("group1".equals(results[0])) {
                    fileServer = group1;
                } else if ("group2".equals(results[0])) {
                    fileServer = group2;
                } else if ("group3".equals(results[0])) {
                    fileServer = group3;
                } else if ("group4".equals(results[0])) {
                    fileServer = group4;
                } else if ("group5".equals(results[0])) {
                    fileServer = group5;
                } else if ("group6".equals(results[0])) {
                    fileServer = group6;
                } else if ("group7".equals(results[0])) {
                    fileServer = group7;
                } else if ("group8".equals(results[0])) {
                    fileServer = group8;
                } else if ("group9".equals(results[0])) {
                    fileServer = group9;
                }
            }

            remoteFilename = fileServer + results[1];
        } catch (MyException e) {
            logger.error("Upload file " + uploadFileName + " fails");
        }

        return remoteFilename;
    }

    /**
     * 获取文件后缀名，不含.
     *
     * @param fileName
     * @return 文件后缀
     */
    public 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 int deleteFile(String remote_filename, String group_name) throws IOException, MyException {
        if (storageClient == null) {
            init();
        }

        int result = storageClient.delete_file(group_name, remote_filename);
        return result;
    }

    public TrackerClient getTrackerClient() {
        return trackerClient;
    }

    public void setTrackerClient(TrackerClient trackerClient) {
        this.trackerClient = trackerClient;
    }

    public TrackerServer getTrackerServer() {
        return trackerServer;
    }

    public void setTrackerServer(TrackerServer trackerServer) {
        this.trackerServer = trackerServer;
    }

    public StorageServer getStorageServer() {
        return storageServer;
    }

    public void setStorageServer(StorageServer storageServer) {
        this.storageServer = storageServer;
    }

    public StorageClient getStorageClient() {
        return storageClient;
    }

    public void setStorageClient(StorageClient storageClient) {
        this.storageClient = storageClient;
    }

    public String getFileServer() {
        return fileServer;
    }

    public void setFileServer(String fileServer) {
        this.fileServer = fileServer;
    }

    public String getEnv() {
        return env;
    }

    public void setEnv(String env) {
        this.env = env;
    }

    public String getGroup1() {
        return group1;
    }

    public void setGroup1(String group1) {
        this.group1 = group1;
    }

    public String getGroup2() {
        return group2;
    }

    public void setGroup2(String group2) {
        this.group2 = group2;
    }

    public String getGroup3() {
        return group3;
    }

    public void setGroup3(String group3) {
        this.group3 = group3;
    }

    public String getGroup4() {
        return group4;
    }

    public void setGroup4(String group4) {
        this.group4 = group4;
    }

    public String getGroup5() {
        return group5;
    }

    public void setGroup5(String group5) {
        this.group5 = group5;
    }

    public String getGroup6() {
        return group6;
    }

    public void setGroup6(String group6) {
        this.group6 = group6;
    }

    public String getGroup7() {
        return group7;
    }

    public void setGroup7(String group7) {
        this.group7 = group7;
    }

    public String getGroup8() {
        return group8;
    }

    public void setGroup8(String group8) {
        this.group8 = group8;
    }

    public String getGroup9() {
        return group9;
    }

    public void setGroup9(String group9) {
        this.group9 = group9;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }
}
