package com.iformall.ueditor.upload;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.iformall.shiro.UserSession;
import com.iformall.ueditor.define.BaseState;
import com.iformall.ueditor.define.State;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.UUID;

public class Uploader {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private HttpServletRequest request = null;
    private Map<String, Object> conf = null;
    private AmazonS3 s3 = null;

    public Uploader(HttpServletRequest request, Map<String, Object> conf) {
        this.request = request;
        this.conf = conf;
        this.s3 = AmazonS3ClientBuilder.standard()
                .withRegion(conf.get("clientRegion").toString())
                .withCredentials(new AWSCredentialsProvider() {
                    @Override
                    public AWSCredentials getCredentials() {
                        return new BasicAWSCredentials(conf.get("access").toString(), conf.get("secret").toString());
                    }

                    @Override
                    public void refresh() {

                    }
                })
                .build();
    }

    public final State doExec() {
        String filedName = (String) this.conf.get("fieldName");
        State state = null;

        if ("true".equals(this.conf.get("isBase64"))) {
            state = Base64Uploader.save(this.request.getParameter(filedName),
                    this.conf);
        } else {
            MultipartFile multiReq= ((MultipartHttpServletRequest) this.request).getFile("upfile");
            String tenantId = (String)SecurityUtils.getSubject().getSession().getAttribute(UserSession.tenantId);

            String fileName = UUID.randomUUID().toString();
            int dot = multiReq.getOriginalFilename().lastIndexOf('.');
            if (dot >= 0) {
                fileName = tenantId + "/" + fileName + multiReq.getOriginalFilename().substring(dot, multiReq.getOriginalFilename().length());
            } else {
                fileName = tenantId + "/" + fileName;
            }

            state = state = new BaseState(true);
            state.putInfo("size", multiReq.getSize());
            state.putInfo("title", filedName);

            JSONObject stateJson = JSON.parseObject(state.toJSONString());

            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType(multiReq.getContentType());
            metadata.setContentLength(multiReq.getSize());

            try {
                s3.putObject(
                        new PutObjectRequest(conf.get("bucketName").toString(), fileName, multiReq.getInputStream(), metadata)
                                .withCannedAcl(CannedAccessControlList.PublicRead));
                URL url = s3.getUrl(conf.get("bucketName").toString(), fileName);
                //logger.info(url.toString());
                state.putInfo("url", url.toString());
            } catch (AmazonServiceException ase) {
                    /*
                    logger.warn("Caught an AmazonServiceException, which " +
                            "means your request made it " +
                            "to Amazon S3, but was rejected with an error response" +
                            " for some reason.");
                    logger.warn(ase.getMessage());
                    */
                ase.printStackTrace();
            } catch (AmazonClientException ace) {
                    /*
                    logger.warn("Caught an AmazonClientException, which " +
                            "means the client encountered " +
                            "an internal error while trying to " +
                            "communicate with S3, " +
                            "such as not being able to access the network.");
                    logger.warn("Error Message: " + ace.getMessage());
                    */
                ace.printStackTrace();
            } catch (IOException ioe) {
                //logger.warn("Caught an IOException: " + ioe.getMessage());
                ioe.printStackTrace();
            }
        }

        return state;
    }
}
