using System.Text.Json;
using System.Text.Json.Serialization;

namespace View_by_Distance.Shared.Models;

public class Face : Properties.IFace
{

    protected DateTime _DateTime;
    protected FaceDistance? _FaceDistance;
    protected FaceEncoding? _FaceEncoding;
    protected Dictionary<Stateless.FacePart, FacePoint[]>? _FaceParts;
    protected readonly OutputResolution? _OutputResolution;
    protected Location? _Location;
    protected Mapping? _Mapping;
    public DateTime DateTime => _DateTime;
    public FaceDistance? FaceDistance => _FaceDistance;
    public FaceEncoding? FaceEncoding => _FaceEncoding;
    public Dictionary<Stateless.FacePart, FacePoint[]>? FaceParts => _FaceParts;
    public Location? Location => _Location;
    public Mapping? Mapping => _Mapping;
    public OutputResolution? OutputResolution => _OutputResolution;

    [JsonConstructor]
    public Face(DateTime dateTime, FaceDistance? faceDistance, FaceEncoding? faceEncoding, Dictionary<Stateless.FacePart, FacePoint[]>? faceParts, Location? location, Mapping? mapping, OutputResolution? outputResolution)
    {
        _DateTime = dateTime;
        _FaceDistance = faceDistance;
        _FaceEncoding = faceEncoding;
        _FaceParts = faceParts;
        _Location = location;
        _Mapping = mapping;
        _OutputResolution = outputResolution;
    }

    public Face(int locationDigits, int locationFactor, int facesCount, Face face) :
        this(face.DateTime, null, face.FaceEncoding, face.FaceParts, face.Location, null, face.OutputResolution)
    {
        if (face.Location?.Confidence is not null && face.OutputResolution is not null)
            _Location = new(face.Location.Confidence, face.OutputResolution.Height, face.Location, locationDigits, locationFactor, face.OutputResolution.Width, facesCount);
    }

    public Face(Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, Location? location) :
        this(DateTime.MinValue, null, null, null, location, null, null)
    {
        DateTime?[] dateTimes;
        _OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth);
        dateTimes = new DateTime?[] { property.CreationTime, property.LastWriteTime, property.DateTime, property.DateTimeDigitized, property.DateTimeFromName, property.DateTimeOriginal, property.GPSDateStamp };
        _DateTime = (from l in dateTimes where l.HasValue select l.Value).Min();
    }

    public Face(Face face, int height, Location location, int locationDigits, int locationFactor, int width, int zCount) :
        this(face.DateTime, face.FaceDistance, face.FaceEncoding, face.FaceParts, new(height, location, locationDigits, locationFactor, width, zCount), face.Mapping, face.OutputResolution)
    { }

    public override string ToString()
    {
        string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
        return result;
    }

    public void SetFaceEncoding(FaceEncoding faceEncoding) => _FaceEncoding = faceEncoding;

    public void SetFaceParts(Dictionary<Stateless.FacePart, FacePoint[]> faceParts) => _FaceParts = faceParts;

    public void SetMapping(Mapping mapping) => _Mapping = mapping;

    public void SetFaceDistance(FaceDistance? faceDistance) => _FaceDistance = faceDistance;

}