// Copyright 2019 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.

#include "base/LayoutResolver.h"

#include <algorithm>
#include <cmath>
#include <stdint.h>
#include <vector>

namespace android {
namespace base {

/*
 *  An internal struct used for describing a rectangle that could contain a list
 *of "children" rectangles that has to fit in the "parent" rectangle.
 */
struct Rect {
    uint32_t id;
    uint32_t pos_x;
    uint32_t pos_y;
    uint32_t width;
    uint32_t height;
    // indicates that this rectangle is a child of some parent rectangle.
    bool isChild;

    std::vector<uint32_t> children;
    Rect(uint32_t i, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
        : id(i), pos_x(x), pos_y(y), width(w), height(h), isChild(false) {}
};

static double computeScore(const uint32_t combinedWidth,
                           const uint32_t combinedHeight,
                           const uint32_t firstRowWidth,
                           const uint32_t secondRowWidth,
                           const double monitorAspectRatio) {
    if (firstRowWidth == 0 || secondRowWidth == 0) {
        return std::pow((double)combinedHeight / (double)combinedWidth -
                                monitorAspectRatio,
                        2);
    } else {
        return std::pow((double)firstRowWidth / (double)secondRowWidth - 1.0,
                        2) +
               std::pow((double)combinedHeight / (double)combinedWidth -
                                monitorAspectRatio,
                        2);
    }
}
/*
 * Compute the coordinates for each rectangle using the lower left corner as
 * origin. Save the coordinates in @param retVal using id as the key.
 */
static std::unordered_map<uint32_t, std::pair<uint32_t, uint32_t>>
computeCoordinatesPerRow(
        std::vector<Rect>& row,
        uint32_t yOffset,
        std::unordered_map<uint32_t, std::pair<uint32_t, uint32_t>>& displays) {
    std::unordered_map<uint32_t, std::pair<uint32_t, uint32_t>> retVal;
    std::stable_sort(row.begin(), row.end(), [](const Rect& a, const Rect& b) {
        return a.height > b.height || (a.height == b.height && a.id < b.id);
    });
    uint32_t width = 0;
    for (const auto& iter : row) {
        uint32_t displayId = iter.id;
        retVal[displayId] = std::make_pair(width, yOffset);
        uint32_t cumulativeHeight = displays[displayId].second + yOffset;
        for (auto id : iter.children) {
            retVal[id] = std::make_pair(width, cumulativeHeight);
            cumulativeHeight += displays[id].second;
        }
        width += iter.width;
    }
    return retVal;
}

std::unordered_map<uint32_t, std::pair<uint32_t, uint32_t>> resolveLayout(
        std::unordered_map<uint32_t, std::pair<uint32_t, uint32_t>> rect,
        const double monitorAspectRatio) {
    // Combine smaller rectangles into bigger ones by trying every pair of
    // rectangles but always maintain these two invariants. 1, Always start
    // combining from rectangle with smaller width. 2, The height of combined
    // rectangle should not exceed the max height of all the original
    // rectangles. When two smaller rectangles form a new one, update the
    // rectangle with bigger width as the newly-formed rectangle, the smaller
    // one is marked as children.

    std::vector<Rect> rectangles;
    uint32_t maxHeight = 0;
    for (const auto& iter : rect) {
        uint32_t width = iter.second.first;
        uint32_t height = iter.second.second;
        rectangles.emplace_back(iter.first, 0, 0, width, height);
        maxHeight = std::max(maxHeight, height);
    }

    std::stable_sort(
            rectangles.begin(), rectangles.end(),
            [](const Rect& a, const Rect& b) { return a.width < b.width || (a.width == b.width && a.id > b.id); });

    for (int i = 0; i < rectangles.size(); i++) {
        for (int j = i + 1; j < rectangles.size(); j++) {
            if (rectangles[i].height + rectangles[j].height <= maxHeight) {
                rectangles[i].isChild = true;
                rectangles[j].children.push_back(rectangles[i].id);
                if (!rectangles[i].children.empty()) {
                    for (uint32_t it : rectangles[i].children) {
                        rectangles[j].children.push_back(it);
                    }
                }
                rectangles[j].height += rectangles[i].height;
                break;
            }
        }
    }

    // Delete rectangles that are chidlren of others.
    for (auto it = rectangles.begin(); it != rectangles.end();) {
        if (it->isChild) {
            it = rectangles.erase(it);
        } else {
            ++it;
        }
    }

    // Try every enumeration of placing a rectangle into either first or second
    // row to find the best fit. We try to balance two factors: 1, the combined
    // rectangle's aspect ratio will be close to the monitor screen's aspect
    // ratio. 2, the combined width of the first row will be close to the
    // combined width of the second row. After the rectangles are placed into
    // two rows, in each row, the rectangles will be sorted based on height.
    double bestScore = 0;
    int bestScoreBitSet = -1;
    for (int bitset = 0; bitset < 1 << (rectangles.size() - 1); bitset++) {
        uint32_t firstRowWidth = 0;
        uint32_t secondRowWidth = 0;
        uint32_t firstRowHeight = 0;
        uint32_t secondRowHeight = 0;
        for (int idx = 0; idx < rectangles.size(); idx++) {
            if ((1 << idx) & bitset) {
                firstRowWidth += rectangles[idx].width;
                firstRowHeight =
                        std::max(firstRowHeight, rectangles[idx].height);
            } else {
                secondRowWidth += rectangles[idx].width;
                secondRowHeight =
                        std::max(secondRowHeight, rectangles[idx].height);
            }
        }
        uint32_t combinedHeight = firstRowHeight + secondRowHeight;
        uint32_t combinedWidth = std::max(firstRowWidth, secondRowWidth);
        double score =
                computeScore(combinedWidth, combinedHeight, firstRowWidth,
                             secondRowWidth, monitorAspectRatio);
        if (bestScoreBitSet == -1 || score < bestScore) {
            bestScoreBitSet = bitset;
            bestScore = score;
        }
    }

    std::vector<Rect> firstRow, secondRow;
    for (int idx = 0; idx < rectangles.size(); idx++) {
        if ((1 << idx) & bestScoreBitSet) {
            firstRow.push_back(std::move(rectangles[idx]));
        } else {
            secondRow.push_back(std::move(rectangles[idx]));
        }
    }

    std::unordered_map<uint32_t, std::pair<uint32_t, uint32_t>> retVal;
    uint32_t yOffset = 0;
    auto resFirstRow = computeCoordinatesPerRow(firstRow, yOffset, rect);
    retVal.insert(resFirstRow.begin(), resFirstRow.end());
    uint32_t firstRowHeight = (firstRow.empty() ? 0 : firstRow[0].height);

    yOffset = firstRowHeight;
    auto resSecRow = computeCoordinatesPerRow(secondRow, yOffset, rect);
    retVal.insert(resSecRow.begin(), resSecRow.end());

    return retVal;
}

}  // namespace base
}  // namespace android
