package com.fitbank.homebanking;

import com.fitbank.common.exception.FitbankException;
import com.fitbank.common.properties.PropertiesHandler;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import java.io.File;
import java.io.FileOutputStream;

/**
 *
 * @author jemm
 */
public class ImageUploadManager {

    private HttpServletRequest request;
    private int sizeThreshold;
    private long imageMaxSizeInBytes;
    private int imageHeight;
    private int imageWidth;
    private String fileName;
    private String imageExtension;
    private String realFileName;
    private String path;

    /**
     * Entrega el saldo efectivo de una cuenta.
     * @return
     * @throws Exception
     */
    public ImageUploadManager(HttpServletRequest request, int sizeThreshold,
            long imageMaxSizeInBytes, int imageHeight, int imageWidth, String fileName,String path) {
        this.request = request;
        this.sizeThreshold = sizeThreshold;
        this.imageMaxSizeInBytes = imageMaxSizeInBytes;
        this.imageHeight = imageHeight;
        this.imageWidth = imageWidth;
        this.fileName = fileName;
        this.path=path;
    }

    /**
     * Entrega el saldo efectivo de una cuenta.
     * @return
     * @throws Exception
     */
    public void uploadImage() throws Exception {
        boolean isMultipart = ServletFileUpload.isMultipartContent(this.getRequest());
        if (isMultipart) {
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold(this.sizeThreshold);
            ServletFileUpload upload = new ServletFileUpload(factory);
            // upload.setSizeMax(maxSizeInBytes);
            List items = upload.parseRequest(this.getRequest());
            Iterator it = items.iterator();
            FileItem fileItem = null;
            while (it.hasNext()) {
                fileItem = (FileItem) it.next();
                if (!fileItem.isFormField()) {
                    if (this.isImageContentType(fileItem.getContentType())) {
                        if (fileItem.getSize() <= this.imageMaxSizeInBytes) {
                            if (this.isRightSized(fileItem.getInputStream())) {
                                this.saveImage(fileItem.get());
                            } else {
                                throw new FitbankException("HB018", "LA IMAGEN DEL ARCHIVO {0} DEBE TENER DIMENSIONES MENORES O IGUALES A {1} X {2}",
                                        fileItem.getName(), this.imageWidth, this.imageHeight);
                            }
                        } else {
                            throw new FitbankException("HB017", "EL ARCHIVO {0} DEBE TENER UN TAMANIO MENOR O IGUAL A {1} DE BYTES", fileItem.getName(), this.imageMaxSizeInBytes);

                        }
                    } else {
                        throw new FitbankException("HB016", "EL ARCHIVO {0} NO ES UNA IMAGEN O NO TIENE UNA EXTENSION VALIDA", fileItem.getName());
                    }
                }
            }
        } else {
            throw new FitbankException("HB019", "LA PETICION PROCESADA NO ES DEL TIPO multipart/form-data");
        }
    }

    private boolean isRightSized(InputStream inputStream) throws Exception {
        BufferedImage image = ImageIO.read(inputStream);
        if (image.getHeight() > this.imageHeight || image.getWidth() > this.imageWidth) {
            return false;
        }
        return true;
    }

    private boolean isImageContentType(String contentType) throws Exception {
        PropertiesHandler ps = new PropertiesHandler("images");
        List<String> types = ps.getList("imageContentType");
        for (String type : types) {
            if (type.compareTo(contentType) == 0) {
                this.imageExtension = contentType.substring(contentType.lastIndexOf("/")+1);
                return true;
            }
        }
        return false;
    }

    private void saveImage(byte[] b) throws Exception {
        this.realFileName = this.fileName + "." + this.imageExtension;
        File file = new File(this.path + this.realFileName);
        file.createNewFile();
        FileOutputStream os = new FileOutputStream(file);
        os.write(b);
        os.close();
    }

    public HttpServletRequest getRequest() {
        return this.request;
    }

    public String getRealFileName() {
        return this.realFileName;
    }
    
     public String getImageExtension() {
        return this.imageExtension;
    }
}
