package com.atg.openssp.common.provider;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.atg.openssp.common.core.entry.SessionAgent;
import com.atg.openssp.common.exception.NotifyingException;

/**
 * @author <NAME>
 * 
 */
public class WinningNotifier implements Runnable {

	private static final Logger log = LoggerFactory.getLogger(WinningNotifier.class);

	private final String nurl;
	private final float price;
	private final SessionAgent agent;

	private static final int ATTEMPTS = 6;

	public WinningNotifier(final String nurl, final float price, final SessionAgent agent) {
		this.nurl = nurl;
		this.price = price;
		this.agent = agent;
	}

	@Override
	public void run() {
		final String url = MarkupParser.parseNurl(nurl, price);
		if (!StringUtils.isEmpty(url)) {
			boolean failed = false;
			try {
				final String decoded = URLDecoder.decode(url, "UTF-8");
				for (int i = 1; i <= ATTEMPTS; i++) {
					try {
						notifyWinner(decoded);
						if (i > 1) {
							log.info("Notifying finally succeed. Tried {} times. {} [...]", i, decoded.substring(0, 80));
						}
					} catch (final NotifyingException e) {
						log.error("winning notify fails {} {}", i, e.getMessage());
						if (i == ATTEMPTS) {
							log.error("notifying the winner unsuccessful - giving up ...");
							failed = true;
							break;
						}
						try {
							final CountDownLatch latch = new CountDownLatch(1);
							latch.await(100 * (long) i, TimeUnit.MILLISECONDS);
						} catch (final InterruptedException ignore) {}
						continue;
					}
					break;
				}
			} catch (final UnsupportedEncodingException e) {
				log.error(e.getMessage());
			}
			if (!failed) {
				final StringBuilder sb = new StringBuilder();
				sb.append(agent.getRequestid()).append("#").append(price).append("#").append(url);
				log.info("{}", sb.toString());
			}
		}
	}

	private void notifyWinner(final String url) throws NotifyingException {
		final HttpPost httpPost = new HttpPost(url);
		final CloseableHttpClient httpclient = HttpClientBuilder.create().build();
		final RequestConfig config = RequestConfig.custom().setConnectTimeout(2000).setSocketTimeout(2000).setExpectContinueEnabled(false).build();
		httpPost.setConfig(config);

		CloseableHttpResponse httpResponse = null;
		int statusCode = -1;
		try {
			httpResponse = httpclient.execute(httpPost);
			statusCode = httpResponse.getStatusLine().getStatusCode();
		} catch (final IOException e) {
			throw new NotifyingException(url.substring(0, 80) + " [...] ," + e.getMessage() + ", status " + statusCode + ".");
		} finally {
			httpPost.releaseConnection();
			try {
				httpclient.close();
				if (httpResponse != null) {
					httpResponse.close();
				}
			} catch (final IOException e) {
				log.error(e.getMessage());
			}
		}
	}
}
