package it.enea.cruise.data;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;


@JsonInclude(JsonInclude.Include.NON_NULL)
public class ElectricMeterReading {
	
	private String timezone;
	
	public ElectricMeterReading(String timezone) {
		if (timezone.equals("Europe/Rome"))
			this.timezone = "UTC+2";
		else
			this.timezone = timezone;
	}
	
	@JsonProperty("UrbanDataset")
	public UrbanDataset urbanDataset;

	public class Id {
		public String value;
		public String schemeID;

		public Id() {
			schemeID = "SCPS";
			value = "ElectricMeterReading-2.0";
		}
	}

	public class SubProperties {
		@JsonInclude(JsonInclude.Include.NON_NULL)
		public List<String> propertyName; // = new ArrayList<String>();

		public List<String> getPropertyName() {
			return this.propertyName;
		}
	}

	public class PropertyDefinition {
		public String propertyName;
		public String propertyDescription;
		@JsonInclude(JsonInclude.Include.NON_NULL)
		public String dataType;
		@JsonInclude(JsonInclude.Include.NON_NULL)
		public String unitOfMeasure;
		@JsonInclude(JsonInclude.Include.NON_NULL)
		public String codeList;
		@JsonInclude(JsonInclude.Include.NON_NULL)
		SubProperties subProperties;

		public PropertyDefinition(String propName, String propDesc, String dataType, String unitOfMeasure,
				String codeList, SubProperties subProperties) {
			this.propertyName = propName;
			this.propertyDescription = propDesc;
			this.dataType = dataType;
			this.unitOfMeasure = unitOfMeasure;
			this.codeList = codeList;
			if (subProperties != null) {
				this.subProperties = subProperties;
			}
		}
		
		public SubProperties getSubProperties() {
			return subProperties;
		}

		public void setSubProperties(SubProperties subProperties) {
			this.subProperties = subProperties;
		}
		
		public PropertyDefinition() {
			//this.subProperties = new SubProperties();
		}
	}

	public class Properties {
		public List<PropertyDefinition> propertyDefinition;// = new ArrayList<PropertyDefinition>();

		public Properties() {
			propertyDefinition = new ArrayList<PropertyDefinition>();
			PropertyDefinition propDefEN = new PropertyDefinition();
			propDefEN.propertyName = "ActiveEnergy";
			propDefEN.propertyDescription = "Energia attiva consumata";
			propDefEN.dataType = "double";
			propDefEN.unitOfMeasure = "kilowattHour";
			this.propertyDefinition.add(propDefEN);

			SubProperties peridSubProp = new SubProperties();
			peridSubProp.propertyName = new ArrayList<String>();
			peridSubProp.propertyName.add("start_ts");
			peridSubProp.propertyName.add("end_ts");
			PropertyDefinition propDefPer = new PropertyDefinition("period",
					"Periodo durante il quale sono stati rilevati i dati riportati nella riga", null, null, null,
					peridSubProp);
			this.propertyDefinition.add(propDefPer);

			PropertyDefinition propDefStartTS = new PropertyDefinition();
			propDefStartTS.propertyName = "start_ts";
			propDefStartTS.propertyDescription = "Marca temporale indicante l'inizio del periodo";
			propDefStartTS.dataType = "dateTime";
			propDefStartTS.unitOfMeasure = "dimensionless";
			this.propertyDefinition.add(propDefStartTS);

			PropertyDefinition propDefEndTS = new PropertyDefinition();
			propDefEndTS.propertyName = "end_ts";
			propDefEndTS.propertyDescription = "Marca temporale indicante la fine del periodo";
			propDefEndTS.dataType = "dateTime";
			propDefEndTS.unitOfMeasure = "dimensionless";
			this.propertyDefinition.add(propDefEndTS);

			PropertyDefinition propDefPower = new PropertyDefinition();
			propDefPower.propertyName = "ActivePower";
			propDefPower.propertyDescription = "Potenza attiva fase";
			propDefPower.dataType = "double";
			propDefPower.unitOfMeasure = "kilowatt";
			this.propertyDefinition.add(propDefPower);
			
			PropertyDefinition propDefMaxPower = new PropertyDefinition();
			propDefMaxPower.propertyName = "MaxActivePower";
			propDefMaxPower.propertyDescription = "Potenza massima attiva fase";
			propDefMaxPower.dataType = "double";
			propDefMaxPower.unitOfMeasure = "kilowatt";
			this.propertyDefinition.add(propDefMaxPower);

		}
	}

	public class Specification {
		public String version;
		public Id id;
		public String name;
		public String uri;
		public Properties properties;

		public Specification() {
			version = "2.0";
			name = "Electrict Meter Reading";
			uri = "https://smartcityplatform.enea.it/specification/semantic/2.0/ontology/scps-ontology-2.0.owl#ElectricMeterReading";
			properties = new Properties();
			id = new Id();
		}
	}

	public class Producer {
		public String id;
		public String schemeID;
		
		public Producer () {
			this.id = "id0";
			this.schemeID = "schemeID0";
		}
	}

	public class Coordinates {
		public String format;
		public double latitude;
		public double longitude;
		public double height;
		
		public Coordinates () {
			this.format = "WGS84-DD";
			this.latitude = 0.0;
			this.longitude = 0.0;
			this.height = 0.0;
		}
	}

	public class Context {
		public Producer producer;
		public String timeZone;
		@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss", timezone = JsonFormat.DEFAULT_TIMEZONE)
		public Date timestamp;
		public Coordinates coordinates;
		public String language;
		
		public Context () {
			this.producer = new Producer();
			this.timeZone = timezone;
			
			this.timestamp = new Date();
			this.coordinates = new Coordinates();
			this.language = "IT";
		}
	}

	public class Period {
	
		@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss", timezone = JsonFormat.DEFAULT_TIMEZONE)
			public Date start_ts;
		@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss", timezone = JsonFormat.DEFAULT_TIMEZONE)
			public Date end_ts;

		public String toString() {
			return "Start_ts: " + start_ts + " end_ts: " + end_ts;
		}
	}

	public class Property {
		public String name;
		public String val;

		public Property() {
		}

		public Property(String propName, String value) {
			this.name = propName;
			this.val = value;
		}
	}

	public class Line {
		public int id;
		@JsonInclude(JsonInclude.Include.NON_NULL)
		public Coordinates coordinates;
		public Period period;
		public List<Property> property;

		public Line() {
		};

		public Line(Integer i, Period period, List<Property> props) {
			this.id = i;
			this.period = period;
			this.property = props;
		}

	}

	public class Values {
		public List<Line> line;
	}

	public class UrbanDataset {
		public Specification specification;
		
		@JsonInclude(JsonInclude.Include.NON_NULL)
		public Context context;
		public Values values;
		
		public UrbanDataset () {
			this.specification = new Specification();
			this.context = new Context();
			this.values = new Values();
		}
	}

	public UrbanDataset generateEmptyUDS() {
		UrbanDataset uds = new UrbanDataset();
		return uds;
	}

}
