/*******************************************************************************
 * Copyright (c) 2012 Rushan R. Gilmullin and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0 
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 *     Rushan R. Gilmullin - initial API and implementation
 *******************************************************************************/
package org.eclipse.osbp.vaaclipse.theme;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.osbp.vaaclipse.publicapi.theme.Theme;
import org.eclipse.osbp.vaaclipse.publicapi.theme.ThemeContribution;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.wiring.BundleWiring;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ThemeImpl extends ThemeEntryImpl implements Theme {

	private static final String PLATFORM_PLUGIN = "platform:/plugin/";

	private static final String PLATFORM_RESOURCE = "platform:/resource/";

	private static final Logger LOGGER = LoggerFactory.getLogger(ThemeImpl.class);

	private static List<String> imageExtensions = new ArrayList<String>();
	static {
		imageExtensions.add("png");
		imageExtensions.add("gif");
		imageExtensions.add("jpg");
		imageExtensions.add("jpeg");
	}

	private String label;
	private String description;
	private List<ThemeContribution> contributions = new ArrayList<ThemeContribution>();
	private List<Theme> inheritedThemes = new ArrayList<Theme>();

	private List<String> cssCashList;
	private List<String> resourcesCashList;

	private byte[] cssBytes;

	public ThemeImpl(String id, String label) {
		super(id);
		this.label = label;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getLabel() {
		return label;
	}

	@Override
	public String getDescription() {
		return this.description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	@Override
	public List<Theme> getInheritedThemes() {
		return Collections.unmodifiableList(this.inheritedThemes);
	}

	@Override
	public List<ThemeContribution> getContributions() {
		return Collections.unmodifiableList(this.contributions);
	}

	public void addContribution(ThemeContribution contibution) {
		this.resourcesCashList = null;
		this.cssCashList = null;
		this.contributions.add(contibution);
	}

	public void addInheritedTheme(Theme theme) {
		this.resourcesCashList = null;
		this.cssCashList = null;
		this.inheritedThemes.add(theme);
	}

	@Override
	public String toString() {
		return "Theme [id=" + id + ", label='" + label;
	}

	@Override
	public List<String> getAllCssURIs() {
		if (cssCashList == null) {
			cssCashList = new ArrayList<String>();
			cssCashList.add(getCssUri());

			for (Theme theme : this.getInheritedThemes()) {
				cssCashList.addAll(theme.getAllCssURIs());
			}

			for (ThemeContribution c : this.getContributions()) {
				if (c.getCssUri() != null)
					cssCashList.add(c.getCssUri());
			}
		}
		return cssCashList;
	}

	@Override
	public List<String> getAllResourceLocationURIs() {
		if (resourcesCashList == null) {
			resourcesCashList = new ArrayList<String>();
			resourcesCashList.addAll(getResourceLocationURIs());

			for (Theme theme : this.getInheritedThemes()) {
				resourcesCashList.addAll(theme.getAllResourceLocationURIs());
			}

			for (ThemeContribution c : this.getContributions()) {
				resourcesCashList.addAll(c.getResourceLocationURIs());
			}
		}
		return Collections.unmodifiableList(resourcesCashList);
	}

	@Override
	public InputStream getCssAsStream() {
		return new ByteArrayInputStream(cssBytes);
	}

	@Override
	public InputStream getThemeResourceAsStream(String themeUri) {
		InputStream in = getResourceAsStreamInternal(themeUri, true);
		return in;
	}

	private InputStream getResourceAsStreamInternal(String themeUri, boolean useDefault) {
		InputStream in = null;
		StringBuffer buffer = new StringBuffer(themeUri);
		for (String resLocUri : getAllResourceLocationURIs()) {
			String bundlePath = resLocUri + themeUri;
			try {
				URL u = new URL(bundlePath);
				in = u.openStream();
				break;
			} catch (Exception ex) {
				buffer.append(":\n").append(ex.getClass().getName()).append(" in ").append(resLocUri).append("\n");
			}
		}
		if (in == null) {
			if (useDefault) {
				return getResourceAsStreamInternal("icon/nopic_small.png", false);
			} else {
				LOGGER.debug("{}", buffer);
			}
		}
		return in;
	}

	void prepareTheme() throws Exception {
		StringBuffer inheritedBuffer = new StringBuffer();
		for (Theme inherited : inheritedThemes) {
			inheritedBuffer.append(String.format("@import \"../%s/styles.css\";", inherited.getWebId()));
		}

		List<ThemeContributionImpl> afterMainCss = new ArrayList<ThemeContributionImpl>();
		List<ThemeContributionImpl> afterInheritedImports = new ArrayList<ThemeContributionImpl>();
		List<ThemeContributionImpl> beforeInheritedImports = new ArrayList<ThemeContributionImpl>();
		Map<String, List<ThemeContributionImpl>> bindedContributionsBefore = new HashMap<String, List<ThemeContributionImpl>>();
		Map<String, List<ThemeContributionImpl>> bindedContributionsAfter = new HashMap<String, List<ThemeContributionImpl>>();

		for (ThemeContribution c : this.contributions) {
			if (c.getCssUri() == null)
				continue;

			ThemeContributionImpl contribution = (ThemeContributionImpl) c;
			String pos = contribution.getInsertPosition();
			String[] split = pos.split("=");
			if (split.length == 2) {
				String mod = split[0].trim();

				if ("after".equals(mod) || "before".equals(mod)) {
					String value = split[1].trim();

					if (mod.equals("after") && ThemeContribution.MAIN_CSS.equals(value)) {
						afterMainCss.add(contribution);
					} else if (mod.equals("after") && ThemeContribution.INHERITED_IMPORTS.equals(value)
							|| mod.equals("before") && ThemeContribution.MAIN_CSS.equals(value)) {
						afterInheritedImports.add(contribution);
					} else if (mod.equals("before") && ThemeContribution.INHERITED_IMPORTS.equals(value)) {
						beforeInheritedImports.add(contribution);
					} else {// value - is contribution id?
						if (mod.equals("before")) {
							if (!bindedContributionsBefore.containsKey(value))
								bindedContributionsBefore.put(value, new ArrayList<ThemeContributionImpl>());
							bindedContributionsBefore.get(value).add(contribution);
						} else if (mod.equals("after")) {
							if (!bindedContributionsAfter.containsKey(value))
								bindedContributionsAfter.put(value, new ArrayList<ThemeContributionImpl>());
							bindedContributionsAfter.get(value).add(contribution);
						}
					}
				}
			}
		}

		StringBuffer afterMainCssContributionsBuffer = buildStringBuffer(afterMainCss, bindedContributionsBefore,
				bindedContributionsAfter);
		StringBuffer afterInheritedImportsContributionsBuffer = buildStringBuffer(afterInheritedImports,
				bindedContributionsBefore, bindedContributionsAfter);
		StringBuffer beforeInheritedImportsContributionsBuffer = buildStringBuffer(beforeInheritedImports,
				bindedContributionsBefore, bindedContributionsAfter);

		String ls = System.lineSeparator();
		String total = beforeInheritedImportsContributionsBuffer.toString() + ls + inheritedBuffer.toString() + ls
				+ afterInheritedImportsContributionsBuffer.toString() + ls + "@import \"original_styles.css\";" + ls
				+ afterMainCssContributionsBuffer.toString() + ls;

		cssBytes = total.getBytes("UTF-8");

		for (Theme inherited : inheritedThemes) {
			if (inherited instanceof ThemeImpl) {
				((ThemeImpl) inherited).prepareTheme();
			}
		}
	}

	@Override
	public List<String> getImageURIs() {
		List<String> result = new ArrayList<String>();
		for (String uri : getAllResourceLocationURIs()) {
			PathPair pair = parsePathPair(uri);
			if (pair == null) {
				continue;
			}

			Bundle target = findBundle(pair.bundle);
			BundleWiring wiring = target.adapt(BundleWiring.class);
			Collection<String> resources = wiring.listResources(pair.folder, "*", BundleWiring.LISTRESOURCES_RECURSE);
			for (String path : resources) {
				if (path.contains(".")) {
					String extension = path.substring(path.lastIndexOf(".") + 1);
					if (imageExtensions.contains(extension)) {
						result.add("platform:/plugin/" + pair.bundle + "/" + path);
					}
				}
			}
		}
		return result;
	}

	private Bundle findBundle(String bundleName) {
		for (Bundle b : FrameworkUtil.getBundle(getClass()).getBundleContext().getBundles()) {
			if (b.getSymbolicName().equals(bundleName)) {
				return b;
			}
		}
		return null;
	}

	private PathPair parsePathPair(String uri) {
		PathPair pair = null;
		if (uri.startsWith(PLATFORM_RESOURCE)) {
			pair = new PathPair();
			// eg platform:/resource/org.my.foo.bundle/images/obj16
			String result = uri.replace(PLATFORM_RESOURCE, "");
			pair.bundle = result.substring(0, result.indexOf("/"));
			String folder = result = result.substring(result.indexOf("/"), result.length());
			pair.folder = folder;
		} else if (uri.startsWith(PLATFORM_PLUGIN)) {
			// eg platform:/plugin/org.my.foo.bundle/images/obj16
			pair = new PathPair();
			String result = uri.replace(PLATFORM_PLUGIN, "");
			pair.bundle = result.substring(0, result.indexOf("/"));
			String folder = result = result.substring(result.indexOf("/"), result.length());
			pair.folder = folder;
		}

		LOGGER.error("Not a valid URI: " + uri);
		return pair;
	}

	private StringBuffer buildStringBuffer(List<ThemeContributionImpl> list,
			Map<String, List<ThemeContributionImpl>> bindedContributionsBefore,
			Map<String, List<ThemeContributionImpl>> bindedContributionsAfter) {
		StringBuffer buffer = new StringBuffer();
		List<ThemeContributionImpl> result = buildList(list, bindedContributionsBefore, bindedContributionsAfter);
		for (ThemeContributionImpl c : result) {
			buffer.append(String.format("@import \"%s.css\";", c.getWebId()));
		}
		return buffer;
	}

	private List<ThemeContributionImpl> buildList(List<ThemeContributionImpl> list,
			Map<String, List<ThemeContributionImpl>> bindedContributionsBefore,
			Map<String, List<ThemeContributionImpl>> bindedContributionsAfter) {
		bindedContributionsBefore = new HashMap<String, List<ThemeContributionImpl>>(bindedContributionsBefore);
		bindedContributionsAfter = new HashMap<String, List<ThemeContributionImpl>>(bindedContributionsAfter);
		List<ThemeContributionImpl> accumulator = new ArrayList<ThemeContributionImpl>();

		int restBefore, restAfter;
		do {
			restBefore = bindedContributionsBefore.size() + bindedContributionsAfter.size();
			for (ThemeContributionImpl c : list) {

				List<ThemeContributionImpl> bindedList = bindedContributionsBefore.remove(c.getId());
				if (bindedList != null)
					accumulator.addAll(bindedList);

				accumulator.add(c);

				bindedList = bindedContributionsAfter.remove(c.getId());
				if (bindedList != null)
					accumulator.addAll(bindedList);
			}
			restAfter = bindedContributionsBefore.size() + bindedContributionsAfter.size();
			list = accumulator;
			accumulator = new ArrayList<ThemeContributionImpl>();
		} while (restBefore != restAfter);

		return list;
	}

	private static class PathPair {
		private String bundle;
		private String folder;
	}
}
