package cn.myapps.runtime.common.servlet;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Locale;

import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import cn.myapps.authtime.common.service.AuthTimeServiceManager;
import cn.myapps.base.web.WebUser;
import cn.myapps.common.util.StringUtil;
import cn.myapps.util.http.CookieUtil;
import cn.myapps.util.property.MultiLanguageProperty;

/**
 * Spring MVC 的多语言拦截处理器，用于运行时的RESTful API 返回的json数据支持国际化标签
 * @author Happy
 *
 */
public class MultiLanguageHandlerInterceptor extends HandlerInterceptorAdapter {
	
	

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		return super.preHandle(request, response, handler);
	}

	@Override
	public void afterConcurrentHandlingStarted(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		// TODO Auto-generated method stub
		super.afterConcurrentHandlingStarted(request, response, handler);
	}

	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		super.postHandle(request, response, handler, modelAndView);
	}

	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		super.afterCompletion(request, response, handler, ex);
		System.err.println("afterCompletion");
		response.getWriter().write("###afterCompletion###");
		/*MultiLanguageHttpServletResponse resp = new MultiLanguageHttpServletResponse(response);
		response = resp;*/
		
	}
}


class MultiLanguageHttpServletResponse extends HttpServletResponseWrapper{
	
	ByteArrayOutputStream _stream = new ByteArrayOutputStream();  
    PrintWriter _pw = new PrintWriter(_stream);  

	public MultiLanguageHttpServletResponse(HttpServletResponse response) {
		super(response);
		
	}

	 /** 
     * 覆盖getWriter()方法，将字符流缓冲到本地 
     */  
    @Override  
    public PrintWriter getWriter() throws IOException {  
        return _pw;
    }   
    /** 
     * 覆盖getOutputStream()方法，将字节流缓冲到本地 
     */  
    @Override  
    public ServletOutputStream getOutputStream() throws IOException {  
        return new ServletOutputStream(){  
            @Override  
            public void write(int b) throws IOException {  
                _stream.write(b);  
            }

			@Override
			public boolean isReady() {
				// TODO Auto-generated method stub
				return false;
			}

			@Override
			public void setWriteListener(WriteListener writeListener) {
				// TODO Auto-generated method stub
				
			}  
        };  
    }
    
    /** 
     * 获取字节流 
     * @return 
     */  
    public ByteArrayOutputStream getByteArrayOutputStream(){  
        return _stream;  
    }
	
}

class MultiLanguagePrintWriter extends PrintWriter{
	int flag;

	int count;

	int[] buf;

	String domain;

	String language;

	int size;

	public MultiLanguagePrintWriter(ServletRequest inRequ, ServletResponse inResp) throws IOException {

		this(inResp.getWriter(), false);
		this.out = inResp.getWriter();

		HttpServletRequest request = ((HttpServletRequest) inRequ);
		HttpSession session = request.getSession();
		WebUser webUser = AuthTimeServiceManager.getWebUser(request);
		WebUser admin = AuthTimeServiceManager.getAdminUser(request);

		language = CookieUtil.getMultiLanguage(request);
		if (StringUtil.isBlank(language)) {
			Locale loc = request.getLocale();
			if (loc.equals(Locale.CHINA) || loc.equals(Locale.PRC))
				language = "CN";
			else if (loc.equals(Locale.TAIWAN))
				language = "TW";
			else {
				language = loc.getLanguage().toUpperCase();
				if (MultiLanguageProperty.getType(language) == 0) {
					language = "EN";
				}
			}
		}

		if (admin != null) {
			domain = (String) request.getParameter("domain");
		} else if (webUser != null) {
			domain = webUser.getDomainid();
		} else {
			domain = null;
		}
	}

	public MultiLanguagePrintWriter(Writer out, boolean autoFlush) {
		super(out);
		buf = new int[512];
	}

	public void flush() {
		if (count > 0)
			clearBuf();
		super.flush();
	}

	public void close() {
		if (count > 0)
			clearBuf();
		super.close();
	}

	public void write(char buf2[], int off, int len) {
		for (int i = off; i < Math.min(off + len, buf2.length); i++) {
			this.write((int) buf2[i]);
		}
	}

	public void write(String s) {
		write(s.toCharArray(), 0, s.length());
	}

	private void writeToBuf(int b) {
		int newcount = count + 1;
		if (newcount > buf.length) {
			int newbuf[] = new int[Math.max(buf.length << 1, newcount)];
			System.arraycopy(buf, 0, newbuf, 0, count);
			buf = newbuf;
		}
		buf[count] = b;
		count = newcount;
	}

	public void write(int c) {
		switch (c) {
		case '{':
			if (flag == 0) {
				flag = 1;
				writeToBuf(c);
			} else {
				clearBuf();
				super.write(c);
				size++;
			}

			break;
		case '*':
			if (flag == 1) {
				flag = 2;
				writeToBuf(c);
			} else if (flag == 4) {
				flag = 5;
				writeToBuf(c);
			} else {
				clearBuf();
				super.write(c);
				size++;
			}

			break;
		case '[':
			if (flag == 2) {
				flag = 3;
				writeToBuf(c);
			} else {
				clearBuf();
				super.write(c);
				size++;
			}

			break;
		case ']':
			if (flag == 3) {
				flag = 4;
				writeToBuf(c);
			} else {
				clearBuf();
				super.write(c);
				size++;
			}

			break;
		case '}':
			if (flag == 5) {
				writeToBuf(c);
				// start to replace
				String origText = StringUtil.toString(buf, 3, count - 6);
				String newText = MultiLanguageProperty.replaceText(domain, language, origText);
				try {
					super.write(newText);
					size += newText.getBytes("UTF-8").length;
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
				count = 0;
				flag = 0;
			} else {
				clearBuf();
				super.write(c);
				size++;
			}

			break;

		default:
			if (flag == 3) {
				writeToBuf(c);
			} else {
				if (count > 0)
					clearBuf();
				super.write(c);
				size++;
			}

			break;
		}
	}

	private void clearBuf() {
		for (int i = 0; i < count; i++) {
			super.write(buf[i]);
			size++;
		}
		count = 0;
		flag = 0;
	}

	public int getSize() {
		return size;
	}
}


