/*
 *
 *  Copyright (C) 2022 Andrew Gegg
 *
 * 	This file is part of the Gardeners Notebook application
 *
 *  The Gardeners Notebook application is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU 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 General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/gpl.html>.
 *
 *
 */

/*
	Change log
    3.0.2	First version
 */

package uk.co.gardennotebook;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import uk.co.gardennotebook.fxbean.*;
import uk.co.gardennotebook.spi.GNDBException;
import uk.co.gardennotebook.util.StoryLineTree;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
 *  Utility class to check earliest and latest dates allowed for an item in a Storyline.
 *  An item with a mother cannot be dated before the mother.
 *  An item with daughters cannot be dated after the earliest (eldest) daughter.
 *
 *	@author Andy Gegg
 *	@version	3.0.2
 *	@since	3.0.2
 */
final class EditorDateRangeChecker
{
    private static final Logger LOGGER = LogManager.getLogger();

    final private LocalDate minDate;
    final private LocalDate maxDate;

    EditorDateRangeChecker(INotebookBean item)
    {
        LocalDate minDateTry = LocalDate.MIN;
        LocalDate maxDateTry = LocalDate.MAX;
        try
        {
            if (item.hasAncestor())
            {
                StoryLineTree<? extends INotebookBean> history = item.getAncestors();
                LOGGER.debug("After getAncestors: history: {}", history);
                final INotebookBean parent = history.getValue();
                LOGGER.debug("parent: {}", parent);
                List<INotebookBean> ancestry = new ArrayList<>();
                history.walkTree((v,l) -> ancestry.add(v));
                final INotebookBean ancestor = ancestry.get(ancestry.size()-2);	//	the last entry is thisValueBean

                minDateTry = switch (ancestor)
                        {
                            case HusbandryBean hu -> hu.getDate();
                            case GroundworkBean gw -> gw.getDate();
                            case AfflictionEventBean ae -> ae.getDate();
                            case PurchaseItemBean pi -> pi.getPurchase().getDate();
                            default -> throw new IllegalStateException("Unexpected value: " + parent);
                        };
            }
            if (item.hasDescendant())
            {
                StoryLineTree<? extends INotebookBean> history = item.getDescendants();
                LOGGER.debug("After getDescendants: history: {}", history);
                List<? extends StoryLineTree<? extends INotebookBean>> progeny = history.getChildren();
                LOGGER.debug("progeny: {}", progeny);

                for (var sprog : progeny)
                {
                    final INotebookBean child = sprog.getValue();
                    final LocalDate itemDate = switch (child)
                            {
                                case HusbandryBean hu -> hu.getDate();
                                case GroundworkBean gw -> gw.getDate();
                                case AfflictionEventBean ae -> ae.getDate();
                                case PurchaseItemBean pi -> pi.getPurchase().getDate();
                                default -> throw new IllegalStateException("Unexpected value: " + item);
                            };
                    if (itemDate.isBefore(maxDateTry))
                    {
                        maxDateTry = itemDate;
                    }
                }
                LOGGER.debug("maxDateTry: {}", maxDateTry);
            }
        }
        catch (GNDBException ex)
        {
            PanicHandler.panic(ex);
        }

        minDate = minDateTry;
        maxDate = maxDateTry;
    }

    public LocalDate getMinDate()
    {
        return minDate;
    }

    public LocalDate getMaxDate()
    {
        return maxDate;
    }

    @Override
    public String toString()
    {
        return "EditorDateRangeChecker: " +
                "minDate: " + minDate +
                ", maxDate: " + maxDate;
    }

}
