/*
 * Copyright 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "DisplayTopologyValidator"

#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <ftl/enum.h>
#include <input/DisplayTopologyGraph.h>
#include <input/PrintTools.h>
#include <log/log_main.h>
#include <ui/LogicalDisplayId.h>

#include <algorithm>

#define INDENT "  "

namespace android {

namespace {

std::string logicalDisplayIdToString(const ui::LogicalDisplayId& displayId) {
    return base::StringPrintf("displayId(%d)", displayId.val());
}

std::string adjacentDisplayToString(const DisplayTopologyAdjacentDisplay& adjacentDisplay) {
    return adjacentDisplay.dump();
}

std::string floatRectToString(const FloatRect& floatRect) {
    std::string dump;
    dump += base::StringPrintf("FloatRect(%f, %f, %f, %f)", floatRect.left, floatRect.top,
                               floatRect.right, floatRect.bottom);
    return dump;
}

std::string displayPropertiesToString(const DisplayTopologyGraph::Properties& displayProperties) {
    std::string dump;
    dump += "AdjacentDisplays: ";
    dump += dumpVector(displayProperties.adjacentDisplays, adjacentDisplayToString);
    dump += '\n';
    dump += base::StringPrintf("Density: %d", displayProperties.density);
    dump += '\n';
    dump += "Bounds: ";
    dump += floatRectToString(displayProperties.boundsInGlobalDp);
    dump += '\n';
    return dump;
}

DisplayTopologyPosition getOppositePosition(DisplayTopologyPosition position) {
    switch (position) {
        case DisplayTopologyPosition::LEFT:
            return DisplayTopologyPosition::RIGHT;
        case DisplayTopologyPosition::TOP:
            return DisplayTopologyPosition::BOTTOM;
        case DisplayTopologyPosition::RIGHT:
            return DisplayTopologyPosition::LEFT;
        case DisplayTopologyPosition::BOTTOM:
            return DisplayTopologyPosition::TOP;
    }
}

bool validatePrimaryDisplay(
        ui::LogicalDisplayId primaryDisplayId,
        const std::unordered_map<ui::LogicalDisplayId, DisplayTopologyGraph::Properties>&
                topologyGraph) {
    return primaryDisplayId != ui::LogicalDisplayId::INVALID &&
            topologyGraph.contains(primaryDisplayId);
}

bool validateTopologyGraph(
        const std::unordered_map<ui::LogicalDisplayId, DisplayTopologyGraph::Properties>&
                topologyGraph) {
    for (const auto& [sourceDisplay, displayProperties] : topologyGraph) {
        if (!sourceDisplay.isValid()) {
            LOG(ERROR) << "Invalid display in topology graph: " << sourceDisplay;
            return false;
        }
        if (displayProperties.boundsInGlobalDp.getHeight() <= 0 ||
            displayProperties.boundsInGlobalDp.getWidth() <= 0) {
            LOG(ERROR) << "Invalid display-bounds for " << logicalDisplayIdToString(sourceDisplay)
                       << " in topology graph: "
                       << floatRectToString(displayProperties.boundsInGlobalDp);
            return false;
        }
        if (displayProperties.density <= 0) {
            LOG(ERROR) << "Invalid density for " << logicalDisplayIdToString(sourceDisplay)
                       << "in topology graph: " << displayProperties.density;
            return false;
        }
        for (const DisplayTopologyAdjacentDisplay& adjacentDisplay :
             displayProperties.adjacentDisplays) {
            const auto adjacentGraphIt = topologyGraph.find(adjacentDisplay.displayId);
            if (adjacentGraphIt == topologyGraph.end()) {
                LOG(ERROR) << "Missing adjacent display in topology graph: "
                           << adjacentDisplay.displayId << " for source " << sourceDisplay;
                return false;
            }
            std::vector<DisplayTopologyAdjacentDisplay> reverseEdges;
            for (const auto& edge : adjacentGraphIt->second.adjacentDisplays) {
                if (edge.displayId == sourceDisplay) {
                    reverseEdges.push_back(edge);
                }
            }
            if (reverseEdges.empty()) {
                LOG(ERROR) << "Missing reverse edge in topology graph for: " << sourceDisplay
                           << " -> " << adjacentDisplay.displayId;
                return false;
            }

            DisplayTopologyPosition expectedOppositePosition =
                    getOppositePosition(adjacentDisplay.position);
            const auto reverseEdgeIt =
                    std::find_if(reverseEdges.begin(), reverseEdges.end(),
                                 [expectedOppositePosition](
                                         const DisplayTopologyAdjacentDisplay& edge) {
                                     return expectedOppositePosition == edge.position;
                                 });
            if (reverseEdgeIt == reverseEdges.end()) {
                std::string positions;
                for (const auto& edge : reverseEdges) {
                    positions += ftl::enum_string(edge.position);
                    positions += " ";
                }
                LOG(ERROR) << "Reverse edges for: " << sourceDisplay << " -> "
                           << adjacentDisplay.displayId
                           << " found, but none had the expected position: "
                           << ftl::enum_string(expectedOppositePosition) << " actual [" << positions
                           << "]";
                return false;
            }
            if (reverseEdgeIt->offsetDp != -adjacentDisplay.offsetDp) {
                LOG(ERROR) << "Unexpected reverse edge offset: " << sourceDisplay << " -> "
                           << adjacentDisplay.displayId
                           << " expected offset: " << -adjacentDisplay.offsetDp << " actual "
                           << reverseEdgeIt->offsetDp;
                return false;
            }
        }
    }
    return true;
}

bool areTopologyGraphComponentsValid(
        ui::LogicalDisplayId primaryDisplayId,
        const std::unordered_map<ui::LogicalDisplayId, DisplayTopologyGraph::Properties>&
                topologyGraph) {
    return validatePrimaryDisplay(primaryDisplayId, topologyGraph) &&
            validateTopologyGraph(topologyGraph);
}

std::string dumpTopologyGraphComponents(
        ui::LogicalDisplayId primaryDisplayId,
        const std::unordered_map<ui::LogicalDisplayId, DisplayTopologyGraph::Properties>&
                topologyGraph) {
    std::string dump;
    dump += base::StringPrintf("PrimaryDisplayId: %d\n", primaryDisplayId.val());
    dump += base::StringPrintf("TopologyGraph:\n");
    dump += addLinePrefix(dumpMap(topologyGraph, logicalDisplayIdToString,
                                  displayPropertiesToString),
                          INDENT);
    dump += "\n";
    return dump;
}

} // namespace

ui::Transform DisplayTopologyGraph::localPxToGlobalDpTransform(
        ui::LogicalDisplayId displayId) const {
    const auto displayPropertiesIt = graph.find(displayId);
    LOG_ALWAYS_FATAL_IF(displayPropertiesIt == graph.end(), "Invalid display %d in %s",
                        displayId.val(), __func__);
    const auto& displayProperties = displayPropertiesIt->second;

    // Scale to convert from px to DP.
    const float pxToDpScaleFactor = static_cast<float>(ACONFIGURATION_DENSITY_MEDIUM) /
            static_cast<float>(displayProperties.density);
    ui::Transform pxToDpScaleTransform;
    pxToDpScaleTransform.set(pxToDpScaleFactor, 0.0f, 0.0f, pxToDpScaleFactor);

    // Translate origin from local to the topology origin to convert to the global coordinates.
    const auto& displayBounds = displayProperties.boundsInGlobalDp;
    ui::Transform localDpToGlobalDpTransform;
    localDpToGlobalDpTransform.set(displayBounds.left, displayBounds.top);
    return localDpToGlobalDpTransform * pxToDpScaleTransform;
}

ui::Transform DisplayTopologyGraph::globalDpToLocalPxTransform(
        ui::LogicalDisplayId displayId) const {
    const auto displayPropertiesIt = graph.find(displayId);
    LOG_ALWAYS_FATAL_IF(displayPropertiesIt == graph.end(), "Invalid display %d in %s",
                        displayId.val(), __func__);
    const auto& displayProperties = displayPropertiesIt->second;

    // Translate from the topology origin to the destination-display's origin.
    const auto& displayBounds = displayProperties.boundsInGlobalDp;
    ui::Transform globalDpToLocalDpTransform;
    globalDpToLocalDpTransform.set(-displayBounds.left, -displayBounds.top);

    // Scale to convert from dp to px.
    const float dpToPxScaleFactor = static_cast<float>(displayProperties.density) /
            static_cast<float>(ACONFIGURATION_DENSITY_MEDIUM);
    ui::Transform dpToPxScaleTransform;
    dpToPxScaleTransform.set(dpToPxScaleFactor, 0.0f, 0.0f, dpToPxScaleFactor);

    return dpToPxScaleTransform * globalDpToLocalDpTransform;
}

std::string DisplayTopologyAdjacentDisplay::dump() const {
    std::string dump;
    dump += base::StringPrintf("DisplayTopologyAdjacentDisplay: {displayId: %d, position: %s, "
                               "offsetDp: %f}",
                               displayId.val(), ftl::enum_string(position).c_str(), offsetDp);
    return dump;
}

DisplayTopologyGraph::DisplayTopologyGraph(
        ui::LogicalDisplayId primaryDisplay,
        std::unordered_map<ui::LogicalDisplayId, Properties>&& topologyGraph)
      : primaryDisplayId(primaryDisplay), graph(std::move(topologyGraph)) {}

std::string DisplayTopologyGraph::dump() const {
    return dumpTopologyGraphComponents(primaryDisplayId, graph);
}

base::Result<const DisplayTopologyGraph> DisplayTopologyGraph::create(
        ui::LogicalDisplayId primaryDisplay,
        std::unordered_map<ui::LogicalDisplayId, Properties>&& topologyGraph) {
    if (areTopologyGraphComponentsValid(primaryDisplay, topologyGraph)) {
        return DisplayTopologyGraph(primaryDisplay, std::move(topologyGraph));
    }
    return base::Error() << "Invalid display topology components: "
                         << dumpTopologyGraphComponents(primaryDisplay, topologyGraph);
}

} // namespace android
