package jp.sourceforge.shovel.logic.impl;

import static org.seasar.framework.container.ContainerConstants.*;

import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletContext;
import javax.transaction.TransactionManager;

import jp.sourceforge.shovel.SizeType;
import jp.sourceforge.shovel.ThumbnailType;
import jp.sourceforge.shovel.dao.IServerFileDao;
import jp.sourceforge.shovel.entity.GaucheGuess;
import jp.sourceforge.shovel.entity.IServerFile;
import jp.sourceforge.shovel.exception.ApplicationException;
import jp.sourceforge.shovel.logic.IServerFileLogic;

import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;


public class ServerFileLogicImpl implements IServerFileLogic {
    S2Container container_;
    TransactionManager transactionManager_;
    GaucheGuess guess_;

    S2Container getContainer() {
        return SingletonS2ContainerFactory.getContainer();
    }
    private GaucheGuess getGuess() {
        if (guess_ == null) {
            guess_ = new GaucheGuess();
        }
        return guess_;
    }
    IServerFileDao getServerFileDao() {
        return (IServerFileDao)getContainer().getComponent(IServerFileDao.class);
    }
    public void createServerFile(IServerFile serverFile, boolean thumbnail, boolean detectEncoding) throws ApplicationException {
        InputStream inputStream = null;
        ApplicationException e1 = null;
        try {
            String contentType = serverFile.getContentType();
            String charset = null;
            String mime = null;
            if (contentType != null && contentType.length() > 0) {
                int i = contentType.indexOf(";");
                if (i != -1) {
                    mime = contentType.substring(0, i);
                } else {
                    mime = contentType;
                }
                if (detectEncoding) {
                    Pattern pattern = Pattern.compile("^text/.*;.*charset=([a-zA-Z0-9-]+).*$");
                    Matcher matcher = pattern.matcher(contentType);
                    if (matcher.matches()) {
                        charset = matcher.group(0);
                    } else {
                        pattern = Pattern.compile("^text/.*$");
                        matcher = pattern.matcher(contentType);
                        if (matcher.matches()) {
                            inputStream = serverFile.getInputStream();
                            int size = serverFile.getSize();
                            charset = getGuess().guessJP(inputStream, size);
                        }
                    }
                }
            } else {
                mime = serverFile.getMime();
                if (mime != null && mime.length() > 0) {
                    contentType = mime;
                    charset = serverFile.getCharset();
                    if (charset != null && charset.length() > 0) {
                        contentType = mime + ";charset=" + charset;
                    }
                } else {
                    //TODO デフォルトContent-Type
                    mime = "application/octet-stream";
                    contentType = mime;
                }
            }
            long createdTime = Calendar.getInstance().getTimeInMillis();
            serverFile.setCreatedTime(createdTime);
            serverFile.setContentType(contentType);
            serverFile.setCharset(charset);
            serverFile.setMime(mime);
            serverFile.prepare();
            getServerFileDao().insert(serverFile);
            if (thumbnail) {
                for (SizeType sizeType : SizeType.values()) {
                    createThumbnail(serverFile, sizeType);
                }
            }
        } catch (ApplicationException e2) {
            //TODO サムネイルのゴミを消す処理
            e1 = e2;
            throw e1;
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException cause) {
                if (e1 == null) {
                    //TODO
                    e1 = new ApplicationException("");
                    e1.initCause(cause);
                    throw e1;
                }
            }
        }
    }
    public IServerFile createServerFile(String name, String contentType, int size, String charset, InputStream inputStream, boolean detectEncoding) throws ApplicationException {
        if (name == null || name.length() == 0) {
            //TODO
        }
        if (contentType == null || contentType.length() == 0) {
            //TODO
        }
        if (size < 0) {
            //TODO
        }
        if (charset == null || charset.length() == 0) {
            //TODO
        }
        if (inputStream == null) {
            //TODO
        }
        
        IServerFile serverFile = (IServerFile)getContainer().getComponent(IServerFile.class);
        serverFile.setName(name);
        serverFile.setContentType(contentType);
        serverFile.setSize(size);
        serverFile.setCharset(charset);
        serverFile.setInputStream(inputStream);
        createServerFile(serverFile, true, detectEncoding);
        return serverFile;
    }
    public void createThumbnail(IServerFile serverFile, SizeType sizeType) throws ApplicationException {
        if (sizeType.isOriginal()) {
            return;
        }
        ServletContext app = (ServletContext)getContainer().getComponent(SERVLET_CONTEXT_NAME);
        ThumbnailType thumbnailType = (ThumbnailType)app.getAttribute("thumbnail");
        if (thumbnailType.isShovel()) {
            serverFile.createTemporaryThumbnail(sizeType);
        } else if (thumbnailType.isImageMagick()) {
            serverFile.createThumbnail(sizeType);
        }
    }
    public int removeServerFiles(long[] serverFileIds) throws ApplicationException {
        return getServerFileDao().deleteAll(serverFileIds);
    }
    public int removeServerFile(long serverFileId) throws ApplicationException {
        return removeServerFiles(new long[] {serverFileId});
    }
    public IServerFile getServerFile(long serverFileId) {
        return getServerFileDao().find(serverFileId);
    }
    public IServerFile[] getServerFiles(long[] serverFileIds) {
        return getServerFileDao().findAll(serverFileIds, 0, serverFileIds.length);
    }
    public IServerFile[] getServerFiles(int offset, int limit) {
        return getServerFileDao().findAll(null, offset, limit);
    }
}
