/*-
 *  Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
 * 
 *  This file is part of CityDoctor2.
 *
 *  CityDoctor2 is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  CityDoctor2 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 Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with CityDoctor2.  If not, see <https://www.gnu.org/licenses/>.
 */
package de.hft.stuttgart.citydoctor2.utils;

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

import org.citygml4j.model.citygml.ade.ADEComponent;
import org.citygml4j.model.citygml.core.CityModel;
import org.citygml4j.model.gml.geometry.primitives.DirectPosition;

import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.ErrorId;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.quality.model.Edge;
import de.hft.stuttgart.quality.model.Validation;
import de.hft.stuttgart.quality.model.ValidationResult;
import de.hft.stuttgart.quality.model.jaxb.ResultType;

public class QualityADEUtils {

	private QualityADEUtils() {
	}

	public static Edge convertEdge(de.hft.stuttgart.citydoctor2.datastructure.Edge e) {
		DirectPosition from = convertVertex(e.getFrom());
		DirectPosition to = convertVertex(e.getTo());
		Edge result = new Edge();
		result.setFrom(from);
		result.setTo(to);
		return result;
	}

	public static DirectPosition convertVertex(Vector3d v) {
		DirectPosition result = new DirectPosition();
		result.getValue().add(v.getX());
		result.getValue().add(v.getY());
		result.getValue().add(v.getZ());
		return result;
	}

	public static void writeQualityAde(CityObject co) {
		ValidationResult res = new ValidationResult();
		if (co.isValidated()) {
			List<CheckError> errors = new ArrayList<>();
			co.collectContainedErrors(errors);
			if (errors.isEmpty()) {
				res.setResult(ResultType.OK);
			} else {
				res.setResult(ResultType.ERROR);
				for (CheckError e : errors) {
					e.convertToQualityAdeDatastructure().ifPresent(res.getErrors()::add);
				}
			}
		} else {
			res.setResult(ResultType.NOT_CHECKED);
		}
		co.getGmlObject().addGenericApplicationPropertyOfCityObject(res);
	}

	public static void removeValidationResult(CityObject co) {
		for (ADEComponent comp : co.getGmlObject().getGenericApplicationPropertyOfCityObject()) {
			if (comp instanceof ValidationResult) {
				co.getGmlObject().getGenericApplicationPropertyOfCityObject().remove(comp);
				return;
			}
		}
	}

	public static void removeValidation(CityModel cm) {
		for (ADEComponent comp : cm.getGenericApplicationPropertyOfCityModel()) {
			if (comp instanceof Validation) {
				cm.getGenericApplicationPropertyOfCityModel().remove(comp);
				return;
			}
		}
	}

	public static de.hft.stuttgart.quality.model.jaxb.ErrorId mapErrorIdToAdeId(ErrorId key) {
		switch (key.getIdString()) {
		case "GE_R_NOT_CLOSED":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_R_NOT_CLOSED;
		case "GE_R_TOO_FEW_POINTS":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_R_TOO_FEW_POINTS;
		case "GE_R_CONSECUTIVE_POINTS_SAME":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_R_CONSECUTIVE_POINTS_SAME;
		case "GE_R_SELF_INTERSECTION":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_R_SELF_INTERSECTION;
		case "GE_P_NON_PLANAR_POLYGON_NORMALS_DEVIATION":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_P_NON_PLANAR_POLYGON_NORMALS_DEVIATION;
		case "GE_P_NON_PLANAR_POLYGON_DISTANCE_PLANE":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_P_NON_PLANAR_POLYGON_DISTANCE_PLANE;
		case "GE_P_INTERIOR_DISCONNECTED":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_P_INTERIOR_DISCONNECTED;
		case "GE_P_INTERSECTING_RINGS":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_P_INTERSECTING_RINGS;
		case "GE_P_HOLE_OUTSIDE":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_P_HOLE_OUTSIDE;
		case "GE_P_ORIENTATION_RINGS_SAME":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_P_ORIENTATION_RINGS_SAME;
		case "GE_P_INNER_RINGS_NESTED":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_P_INNER_RINGS_NESTED;
		case "GE_S_TOO_FEW_POLYGONS":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_S_TOO_FEW_POLYGONS;
		case "GE_S_NOT_CLOSED":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_S_NOT_CLOSED;
		case "GE_S_NON_MANIFOLD_EDGE":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_S_NON_MANIFOLD_EDGE;
		case "GE_S_POLYGON_WRONG_ORIENTATION":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_S_POLYGON_WRONG_ORIENTATION;
		case "GE_S_ALL_POLYGONS_WRONG_ORIENTATION":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_S_ALL_POLYGONS_WRONG_ORIENTATION;
		case "GE_S_NON_MANIFOLD_VERTEX":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_S_NON_MANIFOLD_VERTEX;
		case "GE_S_SELF_INTERSECTION":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_S_SELF_INTERSECTION;
		case "GE_S_MULTIPLE_CONNECTED_COMPONENTS":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.GE_S_MULTIPLE_CONNECTED_COMPONENTS;
		case "SEM_ATTRIBUTE_WRONG_VALUE":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.SEM_ATTRIBUTE_WRONG_VALUE;
		case "SEM_ATTRIBUTE_MISSING":
			return de.hft.stuttgart.quality.model.jaxb.ErrorId.SEM_ATTRIBUTE_MISSING;
		default:
			throw new IllegalStateException("Cannot map " + key + " to ADE Error Id");
		}
	}

}
