package com.dianping.cat.report.page.jsError;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletException;

import org.unidal.lookup.annotation.Inject;
import org.unidal.web.mvc.PageHandler;
import org.unidal.web.mvc.annotation.InboundActionMeta;
import org.unidal.web.mvc.annotation.OutboundActionMeta;
import org.unidal.web.mvc.annotation.PayloadMeta;

import com.dianping.cat.Cat;
import com.dianping.cat.Constants;
import com.dianping.cat.message.Message;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.message.spi.MessageTree;
import com.dianping.cat.report.ReportPage;

public class Handler implements PageHandler<Context> {
	@Inject
	private JspViewer m_jspViewer;

	private static final String ACCESS = "DirectAccess";

	private String m_data;

	private String m_referer;

	@Override
	@PayloadMeta(Payload.class)
	@InboundActionMeta(name = "jsError")
	public void handleInbound(Context ctx) throws ServletException, IOException {
		// display only, no action here
	}

	@Override
	@OutboundActionMeta(name = "jsError")
	public void handleOutbound(Context ctx) throws ServletException, IOException {
		Model model = new Model(ctx);
		Payload payload = ctx.getPayload();
		long timestamp = payload.getTimestamp();
		String error = payload.getError();
		String file = payload.getFile();
		String host = parseHost();

		if (file == null || file.length() == 0 || (!file.startsWith("http:"))) {
			if (m_referer != null) {
				file = m_referer;
			} else {
				file = "unknown";
			}
		}

		int index = file.indexOf('?');
		if (index > -1) {
			file = file.substring(0, index);
		}
		Cat.logEvent("Error", file, "Error", error);
		Cat.logEvent("Agent", parseValue("Agent", m_data), Message.SUCCESS,
		      new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date(timestamp)));

		MessageTree tree = (MessageTree) Cat.getManager().getThreadLocalMessageTree();

		tree.setDomain(Constants.FRONT_END);
		tree.setHostName(host);
		tree.setIpAddress(host);
		model.setStatus("SUCCESS");
		model.setAction(Action.VIEW);
		model.setPage(ReportPage.JSERROR);
		m_jspViewer.view(ctx, model);
	}

	private String parseHost() {
		MessageTree tree = (MessageTree) Cat.getManager().getThreadLocalMessageTree();
		Message message = tree.getMessage();

		if (message.getType().equals("URL") && message instanceof Transaction) {
			Transaction t = (Transaction) message;
			List<Message> messages = t.getChildren();

			for (Message temp : messages) {
				String name = temp.getName();
				if (name.equals("URL.Server") || name.equals("ClientInfo")) {
					m_data = temp.getData().toString();
					m_referer = parseValue("Referer", m_data);

					if (m_referer != null) {
						try {
							URL u = new URL(m_referer);
							return u.getHost().toLowerCase();
						} catch (MalformedURLException e) {
							break;
						}
					}
				}
			}
		}
		return ACCESS;
	}

	protected String parseValue(final String key, final String data) {
		int len = data == null ? 0 : data.length();
		int keyLen = key.length();
		StringBuilder name = new StringBuilder();
		StringBuilder value = new StringBuilder();
		boolean inName = true;

		for (int i = 0; i < len; i++) {
			char ch = data.charAt(i);

			switch (ch) {
			case '&':
				if (name.length() == keyLen && name.toString().equals(key)) {
					return value.toString();
				}
				inName = true;
				name.setLength(0);
				value.setLength(0);
				break;
			case '=':
				if (inName) {
					inName = false;
				} else {
					value.append(ch);
				}
				break;
			default:
				if (inName) {
					name.append(ch);
				} else {
					value.append(ch);
				}
				break;
			}
		}

		if (name.length() == keyLen && name.toString().equals(key)) {
			return value.toString();
		}

		return null;
	}
}

@@ -1481,24 +1481,60 @@
 rseHost();%0A%0A
+%09%09if (host.contains(%22dianping%22)) %7B%0A%09
 %09%09if (file =
@@ -1595,24 +1595,25 @@
 p:%22))) %7B%0A%09%09%09
+%09
 if (m_refere
@@ -1621,24 +1621,25 @@
  != null) %7B%0A
+%09
 %09%09%09%09file = m
@@ -1651,16 +1651,17 @@
 rer;%0A%09%09%09
+%09
 %7D else %7B
@@ -1657,24 +1657,25 @@
 %09%09%09%7D else %7B%0A
+%09
 %09%09%09%09file = %22
@@ -1687,23 +1687,26 @@
 wn%22;%0A%09%09%09
+%09
 %7D%0A
+%09
 %09%09%7D%0A%0A
+%09
 %09%09int in
@@ -1732,16 +1732,17 @@
 '?');%0A%09%09
+%09
 if (inde
@@ -1751,16 +1751,17 @@
 %3E -1) %7B%0A
+%09
 %09%09%09file 
@@ -1790,18 +1790,20 @@
 dex);%0A%09%09
+%09
 %7D%0A
+%09
 %09%09Cat.lo
@@ -1843,16 +1843,17 @@
 ror);%0A%09%09
+%09
 Cat.logE
@@ -1912,16 +1912,17 @@
 UCCESS,%0A
+%09
 %09%09      
@@ -1993,16 +1993,17 @@
 mp)));%0A%0A
+%09
 %09%09Messag
@@ -2078,16 +2078,17 @@
 e();%0A%0A%09%09
+%09
 tree.set
@@ -2116,16 +2116,17 @@
 T_END);%0A
+%09
 %09%09tree.s
@@ -2145,16 +2145,17 @@
 ost);%0A%09%09
+%09
 tree.set
@@ -2171,16 +2171,20 @@
 (host);%0A
+%09%09%7D%0A
 %09%09model.

add host dianping filter