// Solutions to the Advent Of Code 2024.
// Copyright (C) 2024-2025  Stefan Müller
//
// This program 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/>.

#include <aoc/CeresSearch.hpp>

const std::string CeresSearch::getPuzzleName() const
{
    return "Ceres Search";
}

const int CeresSearch::getPuzzleDay() const
{
    return 4;
}

void CeresSearch::finish()
{
    for (int j = 0; j < lines.size(); j++)
    {
        for (int i = 0; i < lines[j].size(); i++)
        {
            if (lines[j][i] == xmas_[0])
            {
                Point2 start{ i, j };
                computeXmasCount(start);
            }
            else if (lines[j][i] == xmas_[2])
            {
                Point2 start{ i, j };
                computeX_MasCount(start);
            }
        }
    }
}

void CeresSearch::computeXmasCount(const Point2& start)
{
    for (auto d : Point2::directions)
    {
        auto p{ start + d };
        auto i{ 1 };
        while (i < 4 && isInBounds(p) && xmas_[i] == getCharAt(p))
        {
            p += d;
            i++;
        }
        if (i == 4)
        {
            part1++;
        }
    }
}

void CeresSearch::computeX_MasCount(const Point2& start)
{
    auto pUL{ start + Point2::upLeft };
    auto pDR{ start + Point2::downRight };
    auto pUR{ start + Point2::upRight };
    auto pDL{ start + Point2::downLeft };
    if (isInBounds(pUL) && isInBounds(pDR)
        && ((getCharAt(pUL) == xmas_[1] && getCharAt(pDR) == xmas_[3])
            || (getCharAt(pUL) == xmas_[3] && getCharAt(pDR) == xmas_[1]))
        && ((getCharAt(pUR) == xmas_[1] && getCharAt(pDL) == xmas_[3])
            || (getCharAt(pUR) == xmas_[3] && getCharAt(pDL) == xmas_[1])))
    {
        part2++;
    }
}