package com.xxxxxxx.drvpp.fw.web.controller;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.ibatis.session.SqlSession;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.WebRequest;

import com.xxxxxxx.drvpp.fw.common.log.Logger;
import com.xxxxxxx.drvpp.fw.common.log.LoggerFactory;
import com.xxxxxxx.drvpp.fw.common.log.LoggerFactoryBuilder;
import com.xxxxxxx.drvpp.fw.common.mybatis.MyBatisSessionFactory;
import com.xxxxxxx.drvpp.fw.common.util.BeanFactoryBuilder;
import com.xxxxxxx.drvpp.fw.common.util.Setting;
import com.xxxxxxx.drvpp.fw.common.util.SettingFactory;
import com.xxxxxxx.drvpp.fw.web.util.Business;
import com.xxxxxxx.drvpp.fw.web.util.EventParameter;
import com.xxxxxxx.drvpp.fw.web.util.WebParameter;

@Controller
public class ApplicationControllerImpl {
	private String getRequestMapping(String url){
		String id = null;
		if (url.equals("/")){
			id = "id1";
		}
		else if (url.equals("/controller")){
			id = "id2";
		}
		return id;
	}

	@RequestMapping(value = "/**/", method = RequestMethod.GET)
	public String doGet(HttpServletRequest req, HttpServletResponse res, WebRequest request,
			Model model) {
		return doExecute(req, res, request, model);
	}
	
	@RequestMapping(value = "/**/", method = RequestMethod.POST)
	public String doPost(HttpServletRequest req, HttpServletResponse res, WebRequest request,
			Model model) {
		return doExecute(req, res, request, model);
	}

	public String doExecute(HttpServletRequest req, HttpServletResponse res, WebRequest request,
			Model model) {
		return doWebExecute(req, request, model);
	}

	//@RequestMapping(value = "/controller/**/", method = RequestMethod.GET)
	//@RequestMapping(value = "/**/", method = RequestMethod.GET)
	public String doWebExecute(HttpServletRequest req, WebRequest request,
			Model model) {
    	// ロガー取得
    	LoggerFactoryBuilder loggerFactoryBuilder = LoggerFactoryBuilder.getInstance();
    	LoggerFactory loggerFactory = loggerFactoryBuilder.getLoggerFactory();
    	Logger logger = loggerFactory.getLogger(this.getClass());
    	
    	// 設定値取得
    	SettingFactory settingFactory = SettingFactory.getInstance();
    	Setting requestMap = settingFactory.getSystemSetting("requestMap");
    	
		// DBセッション取得
		MyBatisSessionFactory sessionFactory = MyBatisSessionFactory
				.getInstance();
		SqlSession sqlSession = sessionFactory.openSession();

		// アプリケーションコンテキスト取得(Beanの生成に使用)
		BeanFactoryBuilder builder = BeanFactoryBuilder.getInstance();
		ApplicationContext applicationContext = builder.build();

		// リクエストパラメータ
		Map<String, String> requestParameter = new HashMap<String, String>();
		Map<String, String[]> map = req.getParameterMap();
		Set<Entry<String, String[]>> set = map.entrySet();
		for (Iterator<Entry<String, String[]>> it = set.iterator(); it
				.hasNext();) {
			Entry<String, String[]> entry = it.next();
			String key = entry.getKey();
			String value = entry.getValue()[0];
			requestParameter.put(key, value);
		}

		// フローの決定
		String url = req.getRequestURI();
		url = url.substring(req.getContextPath().length());
		String reqId = getRequestMapping(url);
		List<Business> flow = (List<Business>)requestMap.getList(reqId);
		//List<Business> flow = (List<Business>)applicationContext.getBean("businessList");

		// 実行
		WebParameter parameter = null;
		for (Business b : flow) {
			// パラメータ設定
			parameter = new WebParameter();
			parameter.setSqlSession(sqlSession);
			Map<String, Object> input = new HashMap<String, Object>();
			Map<String, Object> output = new HashMap<String, Object>();
			parameter.setInput(input);
			parameter.setOutput(output);
			parameter.setRequestParameter(requestParameter);
			parameter.setRequest(request);
			parameter.setModel(model);
			parameter.setViewName("error");

			int result = -1;
			try {
				// ビジネスロジック起動
				result = b.doExecute(parameter);

				input.clear();
				input.putAll(output);
				output.clear();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				// 起動後処理
				if (result != 0) {
					sqlSession.rollback();
					break;
				}
				sqlSession.commit();
			}
		}

		return parameter.getViewName();
	}

	//@RequestMapping(value = "/rest", method = RequestMethod.POST)
	public void doEventExecute(HttpServletRequest req, HttpServletResponse res) {
    	// ロガー取得
    	LoggerFactoryBuilder loggerFactoryBuilder = LoggerFactoryBuilder.getInstance();
    	LoggerFactory loggerFactory = loggerFactoryBuilder.getLoggerFactory();
    	Logger logger = loggerFactory.getLogger(this.getClass());
    	
		// DBセッション取得
		MyBatisSessionFactory sessionFactory = MyBatisSessionFactory
				.getInstance();
		SqlSession sqlSession = sessionFactory.openSession();

		// アプリケーションコンテキスト取得(Beanの生成に使用)
		BeanFactoryBuilder builder = BeanFactoryBuilder.getInstance();
		ApplicationContext applicationContext = builder.build();

		// リクエストパラメータ
		Map<String, String> requestParameter = new HashMap<String, String>();
		Map<String, String[]> map = req.getParameterMap();
		Set<Entry<String, String[]>> set = map.entrySet();
		for (Iterator<Entry<String, String[]>> it = set.iterator(); it
				.hasNext();) {
			Entry<String, String[]> entry = it.next();
			String key = entry.getKey();
			String value = entry.getValue()[0];
			requestParameter.put(key, value);
		}

		// フローの決定
		List<Business> flow = new ArrayList<Business>();
		Business biz;
		biz = (Business) applicationContext.getBean("businessD");
		flow.add(biz);
		//biz = (Business) applicationContext.getBean("businessB");
		//flow.add(biz);
		//biz = (Business) applicationContext.getBean("businessC");
		//flow.add(biz);

		InputStream is = null;
		OutputStream os = null;
		try {
			is = req.getInputStream();
			os = res.getOutputStream();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		// 実行
		EventParameter parameter = null;
		for (Business b : flow) {
			// パラメータ設定
			parameter = new EventParameter();
			parameter.setSqlSession(sqlSession);
			Map<String, Object> input = new HashMap<String, Object>();
			Map<String, Object> output = new HashMap<String, Object>();
			parameter.setInput(input);
			parameter.setOutput(output);
			parameter.setRequestParameter(requestParameter);
			//parameter.setRequest(request);
			//parameter.setModel(model);
			//parameter.setViewName("error");

			parameter.setInputStream(is);
			parameter.setOutputStream(os);

			int result = -1;
			try {
				// ビジネスロジック起動
				result = b.doExecute(parameter);

				input.clear();
				input.putAll(output);
				output.clear();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				// 起動後処理
				if (result != 0) {
					sqlSession.rollback();
					break;
				}
				sqlSession.commit();
			}
		}

		res.setStatus(200);
	}
}
