/*
 *  Copyright (C) 2006-2013  Ronald Blankendaal
 *  
 *  Many thanks to Manuel J. Gallego for his work on MobyGames querying
 *  for TincoreADB. This file is based on his code.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
package org.dbgl.util.searchengine;

import java.io.IOException;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import org.dbgl.model.SearchEngineImageInformation;
import org.dbgl.model.WebProfile;
import org.dbgl.swtdesigner.SWTImageManager;


public class HotudSearchEngine extends WebSearchEngine {

	private static final String HTML_MULTIPLE_RESULT_MARKER_START = "<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"sectiontable jr_tableview\">";
	private static final String HTML_GAME_TITLE_START = "<div class=\"contentTitle\">";
	private static final String HTML_GAME_END_MARKER = "<!-- END RATINGS COLUMN -->";

	private final static String HOTUD_ORG_HOST_NAME = "www.hotud.org";
	private final static int RESULTS_PER_PAGE = 50;


	private HotudSearchEngine() {}

    private static class SearchEngineHolder {
        private static WebSearchEngine instance = new HotudSearchEngine();
    }

    public static WebSearchEngine getInstance() {
        return SearchEngineHolder.instance;
    }

    public String getIcon() {
		return SWTImageManager.IMG_HOTUD;
	}
    
    public String getName() {
		return "Home o/t Underdogs";
	}
    
    public String getSimpleName() {
		return "hotud";
	}

	public List<WebProfile> getEntries(final String title, String[] platforms) throws IOException {
		int pageIdx = 0;
		int pages = 1;
		List<WebProfile> allEntries = new ArrayList<WebProfile>();
		String platformFilter = platforms.length == 1 ? "/tag/reqs/" + platforms[0]: "";

		while (pageIdx < pages) {
			String content = getResponseContent(HTTP_PROTOCOL + HOTUD_ORG_HOST_NAME + "/component/jreviews/search-results" + platformFilter + "/criteria:3/query:all/scope:title/keywords:"
					+ URLEncoder.encode(title.replaceAll("/", " "), "UTF-8") + "/order:alpha/page:" + (pageIdx + 1) + "/limit:" + RESULTS_PER_PAGE, "UTF-8");
			if (pageIdx == 0)
				pages = getPages(content);
			if (pages > 0) {
				allEntries.addAll(extractEntries(content));
			} else if (content.indexOf("<div class=\"gameInfo_wrapper\">") != -1) {
				allEntries.add(extractSingleEntry(content));
			}
			pageIdx++;
		}
		
		if (platforms.length == 1) {
			for (WebProfile p: allEntries) {
				p.setPlatform(platforms[0].toUpperCase());
			}
		}

		return allEntries;
	}

	private static int getPages(String htmlChunk) {
		int i = htmlChunk.indexOf("<td class=\"jr_pagenav_results\">");
		int j = htmlChunk.indexOf(" results", i);
		if (i == -1 || j == -1) return 0;
		return (int)Math.ceil(Integer.parseInt(htmlChunk.substring(i + 31, j)) / (double)RESULTS_PER_PAGE);
	}

	private static List<WebProfile> extractEntries(String html) {
		List<WebProfile> allEntries = new ArrayList<WebProfile>();
		html = html.replaceAll("\\\\\"", "\"");
		int gameMatchEntryIndex = html.indexOf(HTML_MULTIPLE_RESULT_MARKER_START);
		if (gameMatchEntryIndex != -1)
			gameMatchEntryIndex += HTML_MULTIPLE_RESULT_MARKER_START.length();

		while (gameMatchEntryIndex != -1) {

			gameMatchEntryIndex = html.indexOf("<tr class=\"row" + (allEntries.size() % 2 + 1) + "\">", gameMatchEntryIndex);

			int gameTitleIdx = html.indexOf(HTML_GAME_TITLE_START, gameMatchEntryIndex);
			String gameTitle = extractNextContent(html, gameTitleIdx, HTML_ANCHOR_OPEN, HTML_ANCHOR_CLOSE);
			String url = absoluteUrl(HOTUD_ORG_HOST_NAME, extractNextHrefContent(html, gameTitleIdx));

			int detailsIdx = html.indexOf("<div class=\"jr_customFields\" >", gameTitleIdx + HTML_GAME_TITLE_START.length());
			String details = extractNextContent(html, detailsIdx, HTML_DIV_OPEN, HTML_DIV_CLOSE);
			
			int yearIdx = details.indexOf("<td class=\"fieldLabel\">Year released</td>");
			String year = extractNextContent(details, yearIdx, HTML_ANCHOR_OPEN, HTML_ANCHOR_CLOSE);
			
			WebProfile gameEntry = new WebProfile();
			gameEntry.setTitle(gameTitle);
			gameEntry.setYear(year);
			gameEntry.setUrl(url);
			allEntries.add(gameEntry);

			int endIdx = html.indexOf(HTML_GAME_END_MARKER, gameTitleIdx);
			gameMatchEntryIndex = html.indexOf("<tr class=\"row" + (allEntries.size() % 2 + 1) + "\">", endIdx + HTML_GAME_END_MARKER.length());
		}
		return allEntries;
	}

	private WebProfile extractSingleEntry(String html) {
		int baseIdx = html.indexOf("<base href=");
		String base = extractNextHrefContent(html, baseIdx);
		
		int titleIdx = html.indexOf("<title>");
		String title = extractNextContent(html, titleIdx, HTML_TITLE_OPEN, HTML_TITLE_CLOSE);
		
		int detailsIdx = html.indexOf("<div class=\"gameInfo_wrapper\">", titleIdx);
		
		int yearIdx = html.indexOf("Year released: <a href=", detailsIdx);
		String year = extractNextContent(html, yearIdx, HTML_ANCHOR_OPEN, HTML_ANCHOR_CLOSE);
		
		WebProfile gameEntry = new WebProfile();
		gameEntry.setTitle(title);
		gameEntry.setYear(year);
		gameEntry.setUrl(base);
		
		return setAdditionalFields(gameEntry, html);
	}

	public WebProfile getEntryDetailedInformation(final WebProfile entry) throws UnknownHostException, IOException {
		if (entry.getNotes() != null) return entry;
		return setAdditionalFields(entry, getResponseContent(entry.getUrl(), "UTF-8"));
	}

	private WebProfile setAdditionalFields(WebProfile result, String html) {
		int ratingIdx = html.indexOf("<div class=\"rating_table\">");
		ratingIdx = html.indexOf("<div class=\"rating_value\">", ratingIdx);
		String ratingData = extractNextContent(html, ratingIdx, HTML_DIV_OPEN, HTML_DIV_CLOSE).replace(".", "");
		int rating = 0;
		try {
			rating = new Integer(ratingData);
		} catch (NumberFormatException e) {
			// do nothing
		}
		
		int detailsIdx = html.indexOf("<div class=\"gameInfo_wrapper\">", ratingIdx);
		
		int devIdx = html.indexOf("Developer: <a href=", detailsIdx);
		String developer = extractNextContent(html, devIdx, HTML_ANCHOR_OPEN, HTML_ANCHOR_CLOSE);
		
		int pubIdx = html.indexOf("Publisher: <a href=", detailsIdx);
		String publisher = extractNextContent(html, pubIdx, HTML_ANCHOR_OPEN, HTML_ANCHOR_CLOSE);

		int genreIdx = html.indexOf("Genre: <a href=", detailsIdx);
		String genre = extractNextContent(html, genreIdx, HTML_ANCHOR_OPEN, HTML_ANCHOR_CLOSE);
		
		int platformIdx = html.indexOf("Platform: <a href=", detailsIdx);
		String platform = extractNextContent(html, platformIdx, HTML_ANCHOR_OPEN, HTML_ANCHOR_CLOSE);
		
		int notesIdx = html.indexOf("<div class=\"contentFulltext_wrapper\">", detailsIdx);
		notesIdx = html.indexOf("<div class=\"contentFulltext\">", notesIdx);
		String notes = unescapeHtml(removeAllTags(extractNextContent(html, notesIdx, HTML_DIV_OPEN, HTML_DIV_CLOSE)));

		result.setDeveloperName(developer);
		result.setPublisherName(publisher);
		result.setGenre(genre);
		result.setPlatform(platform);
		result.setNotes(notes);
		result.setRank(rating);
		
		return result;
	}

	public SearchEngineImageInformation[] getEntryImages(final WebProfile entry, int coverArtMax, int screenshotsMax, boolean forceAllRegionsCoverArt) throws IOException {
		entry.setWebImages(new SearchEngineImageInformation[0]);
		return entry.getWebImages();
	}
}
