package org.itscool.weber.controller;

import java.io.IOException;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.itscool.commons.bean.BeanFactory;
import org.itscool.commons.bean.BeanUtil;
import org.itscool.commons.collection.InitParamMap;
import org.itscool.commons.collection.KeyLinkedList;
import org.itscool.commons.dao.EntityInfoMapping;
import org.itscool.commons.document.XmlConfigReader;
import org.itscool.commons.logging.AbstractLog;
import org.itscool.commons.logging.SimpleLog;
import org.itscool.weber.action.*;
import org.itscool.weber.io.MessageConfigReader;
import org.itscool.weber.mapping.ExceptionMappings4x;
import org.itscool.weber.mapping.MessageMappings;

/**
 * scaffoladを実現するサーブレットクラスです<br>
 * 従来のFrontServlet機能を継承しつつ、リクエストURLからアクションとフォームオブジェクト
 * を自動的に検出し、処理します
 */
public class FrontServlet4x extends FrontServlet{
    
    /**
     * サーブレットが初期化されるときに呼ばれます<br>
     * 初期データを設定します
     * @param factory di-config.xmlファイルから初期設定情報を取得するインスタンス
     */
    public void initConfig(BeanFactory factory) throws ServletException {
        ExceptionMappings4x weber2Config = (ExceptionMappings4x)factory.createInstance("ExceptionMappings4x");
        try{
            log = (AbstractLog)factory.getInstance("Log");
            if(!log.isInit()){
                log = (AbstractLog)factory.createInstance("Log");
            }
        }catch(Exception ioe){
            log = SimpleLog.getInstance();
            log.info(ioe.getMessage());
        }
        try{
            MessageMappings messages = MessageMappings.getInstance();
            InitParamMap params = (InitParamMap)factory.createInstance("InitParams");
            String msgConf=params.getParam("message-config");
            
            XmlConfigReader messageReader = new MessageConfigReader();
            messageReader.setConfigName(msgConf);
            messageReader.create(messages);
        }catch(Exception ioe){
            log.info("MessageConfigReaderは実行されません");
        }
        try{
            if( factory.isDefined("EntityInfoMapping") ){
                EntityInfoMapping daoMapping = (EntityInfoMapping)factory.createInstance("EntityInfoMapping");

                String dbType = daoMapping.getDbType();
                log.info("use db type = "+dbType);
            }else{
                log.info("DaoConfigReaderは実行されません");
            }
        }catch(Exception ioe){
            throw new ServletException(ioe.getMessage());
        }
    }
    
    /**
     * 業務処理を呼び出します
     * @param req HttpServletRequestインスタンス
     * @param res HttpServletResponseインスタンス
     * @return 実行結果を表示する画面URLを返します
     */
    protected String invoke(HttpServletRequest req, HttpServletResponse res)
    throws Exception{
        String returnPage = process(req, res);
        return returnPage;
    }
    
    /**
     * リクエストパスからActionインスタンスを取得します。
     * @param path リクエストパスを指定します
     * @return 生成されたActionインスタンス
     */
    public Action getAction(HttpServletRequest req, String path)
    throws IOException {
        ExceptionMappings4x config = (ExceptionMappings4x)ExceptionMappings4x.getInstance();
        BeanFactory factory = BeanFactory.getInstance();
        InitParamMap params = (InitParamMap)factory.createInstance("InitParams");
        String pkgName = params.getParam("pkgName");
        String fileType = params.getParam("fileType");
        RequestDispatcher pathInfo = new RequestDispatcher(path);
        String clazzName = pathInfo.getPkgActionName(pkgName);
        
//        System.out.println(clazzName);
        
        Action action = (Action) BeanUtil.createInstance(clazzName);
        
        action.setForwards(null);
        action.setValidates(null);
        
        return action;
    }
    
    /**
     * リクエストパスからFormBeanインスタンスを取得します。
     * @param path リクエストパスを指定します
     * @return 生成されたFormBeanインスタンス
     */
    public Object getForm(String path) throws IOException{
        ExceptionMappings4x config = (ExceptionMappings4x)ExceptionMappings4x.getInstance();
        
        BeanFactory factory = BeanFactory.getInstance();
        InitParamMap params = (InitParamMap)factory.getInstance("InitParams");
        String pkgName = params.getParam("pkgName");
        String fileType = params.getParam("fileType");
        RequestDispatcher pathInfo = new RequestDispatcher(path);
        String clazzName = pathInfo.getFormName(pkgName);
        if( clazzName == null ){
            return null;
        }
//        System.out.println(clazzName);
        
        Object bean=null;
        try{
            bean = (Object) BeanUtil.createInstance(clazzName);
        }catch(Exception e){
            
        }
        return bean;
    }
    
    /**
     * リクエストURIに指定された権限情報を取得します<BR>
     * 権限情報が定義されていないばあはNULLを返します
     * @param path リクエストされたURI情報
     * @return HashMap このアクションを許可する権限リストを返します
     */
    public HashMap getRoles(String path) {
        HashMap roles = new HashMap();
//        RequestMappings config = (RequestMappings)RequestMappings.getInstance();
//        String pkgName = config.getPkgName();
//        String fileType = config.getFileType();
//        RequestDispatcher pathInfo = new RequestDispatcher(path);
//        String moduleName = pathInfo.getModuleName();
//        String actionName = pathInfo.getActionName();
//        Map roleAction = config.getRolesAction();
//
//        Map roleModule = config.getRolesModule();
//        String roleName = (String)roleAction.get(moduleName+actionName);
//        if(roleName == null){
//            roleName = (String)roleModule.get(moduleName);
//        }
//        if(roleName != null){
//            roles.put(roleName, roleName);
//        }
        return roles;
    }
    
    /**
     * 業務処理実行後の遷移先URLを取得します
     * @param action Actionインスタンス
     * @param ret Actionの実行結果
     * @param path リクエストパス情報
     */
    protected String getForward(Action action, String ret, String path) throws ServletException {
        ExceptionMappings4x config = (ExceptionMappings4x)ExceptionMappings4x.getInstance();
        
        BeanFactory factory = BeanFactory.getInstance();
        InitParamMap params = (InitParamMap)factory.getInstance("InitParams");
        String pkgName = params.getParam("pkgName");
        String fileType = params.getParam("fileType");
        if(fileType.indexOf(".")!=0){
            fileType = "." + fileType;
        }
        RequestDispatcher pathInfo = new RequestDispatcher(path);
        String moduleName = pathInfo.getModuleName();
        String actionName = pathInfo.getActionName();
        String returnPath = pathInfo.getReturnPath(ret);
        returnPath += fileType;
        return returnPath;
    }
    
    /**
     * 例外発生時の遷移先URLを取得します
     * @param e Exception/Errorインスタンス
     * @return 例外発生時の遷移先URL
     */
    protected String getExceptionPage(Object e){
        ExceptionMappings4x config = (ExceptionMappings4x)ExceptionMappings4x.getInstance();
        KeyLinkedList exceptions = config.getExceptions();
        int size = exceptions.size();
        if( size == 0 ) return null;
        String exceptionName = null;
        for(int i=size-1; i>=0; i--){
            String key = (String)exceptions.getKey(i);
            exceptionName = e.getClass().getName();
            if(key.equals(exceptionName)){
                break;
            }
            else{
                try{
                    Class clazz = Class.forName(key);
                    if(clazz.isInstance(e)){
                        exceptionName = key;
                        break;
                    }
                }catch(Exception ex){}
            }
        }
        if( exceptionName == null )return null;
        String exceptionPage = (String)exceptions.get(exceptionName);
        return exceptionPage;
    }
}

