package io.openems.common.oem;

import java.util.Map;

import io.openems.common.session.Language;
import io.openems.common.types.Tuple2;

public interface OpenemsEdgeOem {

	// NOTE: Following values are adopted from SunSpec "Common Model"
	// definition. Please refer to SunSpec documentation for details.

	/**
	 * The manufacturer of the device that is running OpenEMS Edge.
	 *
	 * <p>
	 * Note: this should be max. 32 ASCII characters long
	 *
	 * @return the value
	 */
	public String getManufacturer();

	/**
	 * The model identifier of the device.
	 *
	 * <p>
	 * Note: this should be max. 32 ASCII characters long
	 * 
	 * @return the value
	 */
	public String getManufacturerModel();

	/**
	 * The options of the device.
	 *
	 * <p>
	 * Note: this should be max. 32 ASCII characters long
	 * 
	 * @return the value
	 */
	public String getManufacturerOptions();

	/**
	 * The version of the device.
	 *
	 * <p>
	 * Note: this should be max. 32 ASCII characters long
	 * 
	 * @return the value
	 */
	public String getManufacturerVersion();

	/**
	 * The serial number of the device.
	 *
	 * <p>
	 * Note: this should be max. 32 ASCII characters long
	 * 
	 * @return the value
	 */
	public String getManufacturerSerialNumber();

	/**
	 * The Energy-Management-System serial number of the device.
	 *
	 * <p>
	 * Note: this should be max. 32 ASCII characters long
	 * 
	 * @return the value
	 */
	public String getManufacturerEmsSerialNumber();

	/**
	 * The Websocket URL for OpenEMS Backend.
	 * 
	 * <p>
	 * Note: this value usually starts with "ws://" or "wss://"
	 * 
	 * @return the value
	 */
	public String getBackendApiUrl();

	/**
	 * The measurement Tag used to write data to InfluxDB.
	 * 
	 * <p>
	 * Note: this value defaults to "edge"
	 * 
	 * @return the value
	 */
	public default String getInfluxdbTag() {
		return "edge";
	}

	public record SystemUpdateParams(String packageName, String latestVersionUrl, String updateScriptUrl,
			String updateScriptParams) {
	}

	/**
	 * The parameters for the integrated OpenEMS Edge System-Update feature.
	 * 
	 * <p>
	 * See 'Host' in 'io.openems.edge.common' for details
	 * 
	 * @return the record
	 */
	public SystemUpdateParams getSystemUpdateParams();

	/**
	 * Gets the Website-URL for the given App-ID.
	 * 
	 * @param appId    the App-ID
	 * @param language the language
	 * @return
	 *         <ul>
	 *         <li>a proper URL (e.g. https://...)
	 *         <li>an empty String: App is defined, but no WebsiteUrl is available;
	 *         or
	 *         <li>null: App is undefined
	 *         </ul>
	 */
	public String getAppWebsiteUrl(String appId, Language language);

	/**
	 * Gets the OEM IdentKey for Kaco.BlueplanetHybrid10.Core.
	 * 
	 * @return the value
	 */
	public default String getKacoBlueplanetHybrid10IdentKey() {
		return null;
	}

	/**
	 * Gets the OEM Token for TimeOfUseTariff.ENTSO-E.
	 * 
	 * @return the value
	 */
	public default String getEntsoeToken() {
		return null;
	}

	public record OAuthClientRegistration(String clientId, String clientSecret) {
	}

	public default OAuthClientRegistration getRabotChargeCredentials() {
		return null;
	}

	/**
	 * Gets the OEM authorization for Battery.BMW.
	 * 
	 * @return the value
	 */
	public default Tuple2<String, String> getBmwBatteryAuth() {
		return null;
	}

	/**
	 * Gets the OpenCage API key for geocoding.
	 *
	 * @return the API key
	 */
	public String getOpenCageApiKey();

	/**
	 * Returns the Open-Meteo API key.
	 * 
	 * <p>
	 * The API can also be used without a key for non-commercial use.
	 *
	 * @return the API key, or null if not set
	 */
	public default String getOpenMeteoApiKey() {
		return null;
	}

	/**
	 * Gets the Hardy Barth API key, which is necessary for all versions above 2.2.
	 *
	 * @return the API key
	 */
	public default String getHardyBarthApiToken() {
		return null;
	}

	/**
	 * Returns a link to a given key.
	 * 
	 * @param key the key
	 * @return the link
	 */
	public String getLink(String key);

	/**
	 * Gets the Website Link for a given {@link Language} from a given Map.
	 * 
	 * @param appToWebsiteUrl the map
	 * @param appId           the id of the app
	 * @param language        the {@link Language}
	 * @return the url
	 */
	public static String getAppWebsiteUrlFromMap(//
			Map<String, AppLink> appToWebsiteUrl, //
			String appId, //
			Language language//
	) {
		var appLink = appToWebsiteUrl.get(appId);
		if (appLink == null) {
			return null;
		}
		return appLink.getLinkByLanguage(language) //
				.filter(s -> !s.isBlank()) //
				.or(() -> appLink.getLinkByLanguage(Language.EN) //
						.filter(s -> !s.isBlank()))
				.orElse("");
	}
}
