package com.dianping.cat.report.page.model.spi.internal;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map.Entry;
import java.util.zip.GZIPInputStream;

import org.unidal.helper.Files;
import org.unidal.helper.Urls;
import org.unidal.lookup.annotation.Inject;
import org.xml.sax.SAXException;

import com.dianping.cat.Cat;
import com.dianping.cat.message.Message;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.report.page.model.spi.ModelService;
import com.dianping.cat.service.ModelPeriod;
import com.dianping.cat.service.ModelRequest;
import com.dianping.cat.service.ModelResponse;

public abstract class BaseRemoteModelService<T> extends ModelServiceWithCalSupport implements ModelService<T> {
	@Inject
	private String m_host;

	private String m_name;

	@Inject
	private int m_port = 2281; // default admin port

	@Inject
	private String m_serviceUri = "/cat/r/model";

	public BaseRemoteModelService(String name) {
		m_name = name;
	}

	protected abstract T buildModel(String xml) throws SAXException, IOException;

	public URL buildUrl(ModelRequest request) throws MalformedURLException {
		StringBuilder sb = new StringBuilder(64);

		for (Entry<String, String> e : request.getProperties().entrySet()) {
			if (e.getValue() != null) {
				sb.append('&');
				sb.append(e.getKey()).append('=').append(e.getValue());
			}
		}
		String parameters = "";
		try {
			parameters = URLEncoder.encode(sb.toString(), "utf-8");
		} catch (UnsupportedEncodingException e) {
			Cat.logError(e);
		}
		String url = String.format("http://%s:%s%s/%s/%s/%s?op=xml%s", m_host, m_port, m_serviceUri, m_name,
		      request.getDomain(), request.getPeriod(), parameters);

		return new URL(url);
	}

	@Override
	public String getName() {
		return m_name;
	}

	@Override
	public ModelResponse<T> invoke(ModelRequest request) {
		ModelResponse<T> response = new ModelResponse<T>();
		Transaction t = newTransaction("ModelService", getClass().getSimpleName());

		try {
			URL url = buildUrl(request);

			t.addData(url.toString());

			InputStream in = Urls.forIO().connectTimeout(1000).readTimeout(5000).openStream(url.toExternalForm());
			GZIPInputStream gzip = new GZIPInputStream(in);
			String xml = Files.forIO().readFrom(gzip, "utf-8");

			int len = xml == null ? 0 : xml.length();

			t.addData("length", len);

			if (len > 0) {
				T report = buildModel(xml);

				response.setModel(report);
				t.setStatus(Message.SUCCESS);
			} else {
				t.setStatus("NoReport");
			}
		} catch (Exception e) {
			t.setStatus(e);
		} finally {
			t.complete();
		}

		return response;
	}

	@Override
	public boolean isEligable(ModelRequest request) {
		ModelPeriod period = request.getPeriod();

		return !period.isHistorical();
	}

	public void setHost(String host) {
		m_host = host;
	}

	public void setPort(int port) {
		m_port = port;
	}

	public void setServiceUri(String serviceUri) {
		m_serviceUri = serviceUri;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder(64);

		sb.append(getClass().getSimpleName()).append('[');
		sb.append("name=").append(m_name);
		sb.append(']');

		return sb.toString();
	}
}

@@ -1418,24 +1418,43 @@
 null) %7B%0A%09%09%09%09
+try %7B%0A%09            
 sb.append('&
@@ -1458,19 +1458,28 @@
 ('&');%0A%09
-%09%09%09
+            
 sb.appen
@@ -1515,82 +1515,8 @@
 end(
-e.getValue());%0A%09%09%09%7D%0A%09%09%7D%0A%09%09String parameters = %22%22;%0A%09%09try %7B%0A%09%09%09parameters = 
 URLE
@@ -1529,27 +1529,26 @@
 .encode(
-sb.toString
+e.getValue
 (), %22utf
@@ -1555,40 +1555,33 @@
 -8%22)
-;%0A%09%09%7D catch (UnsupportedEncoding
+ );%0A            %7D catch (
 Exce
@@ -1587,22 +1587,33 @@
 eption e
+x
 ) %7B%0A
-%09%09
+            
 %09Cat.log
@@ -1619,19 +1619,39 @@
 gError(e
+x
 );%0A
+            %7D%0A%09%09%09%7D%0A
 %09%09%7D%0A%09%09St
@@ -1803,18 +1803,21 @@
 (), 
-parameters
+sb.toString()
 );%0A%0A

fix url build bug