/*
 * Copyright (C) 2025  Tim Zimmermann <tim@aglais.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.aglais.zms.db.core.model;

import org.jetbrains.annotations.NotNull;

import java.io.Serial;
import java.io.Serializable;
import java.util.Date;

/**
 * Class representing ancestry info.
 */
public class AncestryData implements Serializable {

    @Serial
    private static final long serialVersionUID = 1;

    private int id;
    private Date dateStart;
    private Date dateEnd;
    private String notes;
    private String generation;
    private int[] parents;
    private Double originLatitude;
    private Double originLongitude;
    private Integer originRadius;

    /**
     * Create a new {@link AncestryData} object.
     *
     * @param id              Ancestry data ID as stored in the Database
     * @param dateStart       Start date associated with this ancestry data
     * @param dateEnd         End date associated with this ancestry data
     * @param notes           Notes related to this ancestry data
     * @param generation      Generation information of this ancestry data
     * @param parents         List of parents of this node
     * @param originLatitude  Latitude coordinate of the origin location of this ancestry data
     * @param originLongitude Longitude coordinate of the origin location of this ancestry data
     * @param originRadius    Radius (in meters) around origin location of this ancestry data
     */
    public AncestryData(int id, Date dateStart, Date dateEnd, String notes, String generation, int @NotNull [] parents,
                        Double originLatitude, Double originLongitude, Integer originRadius) {
        this.id = id;
        this.dateStart = dateStart;
        this.dateEnd = dateEnd;
        this.notes = notes;
        this.generation = generation;
        this.parents = parents;
        this.originLatitude = originLatitude;
        this.originLongitude = originLongitude;
        this.originRadius = originRadius;
    }

    /**
     * No-arg constructor for {@link ModifiedStateTracker}. This constructor creates an empty
     * AncestryData object that can be populated with data later. It is protected to ensure that only
     * classes within the same package or subclasses can create instances without providing
     * initial data.
     */
    protected AncestryData() {

    }

    /**
     * Get the ancestry data ID
     *
     * @return ID from Database, negative temporary value if not yet stored
     */
    public int getID() {
        return id;
    }

    /**
     * Set the ancestry data ID
     *
     * @param id ID from the Database
     */
    public void setID(int id) {
        this.id = id;
    }

    /**
     * Gets the start date.
     *
     * @return The start date
     */
    public Date getDateStart() {
        return dateStart;
    }

    /**
     * Sets the start date.
     *
     * @param dateStart The start date to set
     */
    public void setDateStart(Date dateStart) {
        this.dateStart = dateStart;
    }

    /**
     * Gets the end date.
     *
     * @return The end date
     */
    public Date getDateEnd() {
        return dateEnd;
    }

    /**
     * Sets the end date.
     *
     * @param dateEnd The end date to set
     */
    public void setDateEnd(Date dateEnd) {
        this.dateEnd = dateEnd;
    }

    /**
     * Gets the notes.
     *
     * @return The notes
     */
    public String getNotes() {
        return notes;
    }

    /**
     * Sets the notes.
     *
     * @param notes The notes to set
     */
    public void setNotes(String notes) {
        this.notes = notes;
    }

    /**
     * Gets the generation.
     *
     * @return The generation
     */
    public String getGeneration() {
        return generation;
    }

    /**
     * Sets the generation.
     *
     * @param generation The generation to set
     */
    public void setGeneration(String generation) {
        this.generation = generation;
    }

    /**
     * Get this node's parents
     *
     * @return Array of parents of this node
     */
    public int[] getParents() {
        return parents;
    }

    /**
     * Sets this node's parents
     *
     * @param parents Array of parents of this node
     */
    public void setParents(int[] parents) {
        this.parents = parents;
    }

    /**
     * Gets the latitude coordinate of the origin location associated with this ancestry data.
     *
     * @return Latitude coordinate as a double
     */
    public Double getOriginLatitude() {
        return originLatitude;
    }

    /**
     * Sets the latitude coordinate of the origin location associated with this ancestry data.
     *
     * @param originLatitude Latitude coordinate as a double
     */
    public void setOriginLatitude(Double originLatitude) {
        this.originLatitude = originLatitude;
    }

    /**
     * Gets the longitude coordinate of the origin location associated with this ancestry data.
     *
     * @return Longitude coordinate as a double
     */
    public Double getOriginLongitude() {
        return originLongitude;
    }

    /**
     * Sets the longitude coordinate of the origin location associated with this ancestry data.
     *
     * @param originLongitude Longitude coordinate as a double
     */
    public void setOriginLongitude(Double originLongitude) {
        this.originLongitude = originLongitude;
    }

    /**
     * Gets the radius around the origin location associated with this ancestry data.
     *
     * @return Radius as an integer (in meters)
     */
    public Integer getOriginRadius() {
        return originRadius;
    }

    /**
     * Sets the radius around the origin location associated with this ancestry data.
     *
     * @param originRadius Radius as an integer (in meters)
     */
    public void setOriginRadius(Integer originRadius) {
        this.originRadius = originRadius;
    }

    @Override
    public boolean equals(Object obj) {
        return obj instanceof AncestryData && ((AncestryData) obj).id == this.id;
    }
}