/*
 *   This file is a part of the SteamWar software.
 *
 *   Copyright (C) 2024 SteamWar.de-Serverteam
 *
 *   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 <https://www.gnu.org/licenses/>.
 */

package de.steamwar.kotlin.util

import org.bukkit.Location
import org.bukkit.block.Block

class Area(loc1: Location, loc2: Location) {

    val min: Location
    val max: Location

    init {
        require(loc1.world == loc2.world) { "Locations must be in the same world" }
        this.min = loc1 min loc2
        this.max = loc1 max loc2
    }

    operator fun contains(loc: Location): Boolean {
        return loc.world == min.world && loc.x >= min.x && loc.x <= max.x && loc.y >= min.y && loc.y <= max.y && loc.z >= min.z && loc.z <= max.z
    }

    val blocks: Sequence<Block>
        inline get() = sequence {
            for (x in locations) {
                yield(x.block)
            }
    }

    val locations: Sequence<Location>
        inline get() = sequence {
            for (x in min.blockX..max.blockX) {
                for (y in min.blockY..max.blockY) {
                    for (z in min.blockZ..max.blockZ) {
                        yield(Location(min.world, x.toDouble(), y.toDouble(), z.toDouble()))
                    }
                }
            }
    }
}

infix fun Location.max(other: Location): Location {
    return Location(world, x.coerceAtLeast(other.x), y.coerceAtLeast(other.y), z.coerceAtLeast(other.z))
}

infix fun Location.min(other: Location): Location {
    return Location(world, x.coerceAtMost(other.x), y.coerceAtMost(other.y), z.coerceAtMost(other.z))
}
