/*
 * Copyright Samsung Electronics Co.,LTD.
 * Copyright (C) 2016 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 <algorithm>

#include <log/log.h>

#include <hardware/exynos/acryl.h>

#include "acrylic_internal.h"

Acrylic::Acrylic(const HW2DCapability &capability)
    : mCapability(capability), mHasBackgroundColor(false),
      mMaxTargetLuminance(100), mMinTargetLuminance(0), mTargetDisplayInfo(nullptr),
      mCanvas(this, AcrylicCanvas::CANVAS_TARGET)
{
    ALOGD_TEST("Created a new Acrylic on %p", this);
}

Acrylic::~Acrylic()
{
    mCanvas.disconnectLayer();

    for (auto layer: mLayers) {
        layer->disconnectLayer();
        removeTransitData(layer);
    }

    ALOGD_TEST("Destroyed Acrylic on %p", this);
}

AcrylicLayer *Acrylic::createLayer()
{
    if (mLayers.size() >= getCapabilities().maxLayerCount()) {
        ALOGE("Full of composit layer: current %zu, max %u",
                mLayers.size() , getCapabilities().maxLayerCount());
        return NULL;
    }

    auto *layer = new AcrylicLayer(this);
    if (!layer) {
        ALOGE("Failed to create a new compositing layer");
        return NULL;
    }

    mLayers.push_back(layer);

    ALOGD_TEST("A new Acrylic layer is created. Total %zd layers", mLayers.size());

    return layer;
}

void Acrylic::removeLayer(AcrylicLayer *layer)
{
    auto it = find(std::begin(mLayers), std::end(mLayers), layer);

    if (it == std::end(mLayers)) {
        ALOGE("Deleting an unregistered layer");
    } else {
        removeTransitData(*it);
        mLayers.erase(it);
    }
}

int Acrylic::prioritize(int priority)
{
    if ((priority < -1) || (priority > 15)) {
        ALOGE("Invalid priority %d", priority);
        return -1;
    }

    return 0;
}

bool Acrylic::requestPerformanceQoS(AcrylicPerformanceRequest __unused *request)
{
    return true;
}

bool Acrylic::setHDRToneMapCoefficients(uint32_t __unused *matrix[2], int __unused num_elements)
{
    return true;
}

bool Acrylic::validateAllLayers()
{
    const HW2DCapability &cap = getCapabilities();

    if (!mCanvas.isSettingOkay()) {
        ALOGE("Incomplete settting (flags: %#x) on the target layer",
              mCanvas.getSettingFlags());
        return false;
    }

    if (mCanvas.isCompressed() && !cap.isFeatureSupported(HW2DCapability::FEATURE_AFBC_ENCODE)) {
        ALOGE("AFBC encoding is not supported");
        return false;
    }

    if (mCanvas.isUOrder() && !cap.isFeatureSupported(HW2DCapability::FEATURE_UORDER_WRITE)) {
        ALOGE("Writing in U-Order is not supported");
        return false;
    }

    bool prot = false;
    hw2d_rect_t rect;
    hw2d_coord_t xy = mCanvas.getImageDimension();

    for (auto layer: mLayers) {
        if (!layer->isSettingOkay()) {
            ALOGE("Incomplete settting (flags: %#x) on a layer of %zu layers",
                  layer->getSettingFlags(), mLayers.size());
            return false;
        }

        if (layer->isCompressed() && !cap.isFeatureSupported(HW2DCapability::FEATURE_AFBC_DECODE)) {
            ALOGE("AFBC decoding is not supported");
            return false;
        }

        if (layer->isUOrder() && !cap.isFeatureSupported(HW2DCapability::FEATURE_UORDER_READ)) {
            ALOGE("Reading a texture in U-Order is not supported");
            return false;
        }

        if ((layer->getPlaneAlpha() != 255) && !cap.isFeatureSupported(HW2DCapability::FEATURE_PLANE_ALPHA)) {
            ALOGE("Plane alpha is not supported but given %u for plane alpha", layer->getPlaneAlpha());
            return false;
        }

        rect = layer->getTargetRect();
        if (area_is_zero(rect)) {
            // If no target area is specified to a source layer,
            // the entire region of the target image becomes the target area.
            // Then, check the scaling capability
            hw2d_rect_t ir = layer->getImageRect();
            if (!!(layer->getCompositAttr() & AcrylicLayer::ATTR_NORESAMPLING)) {
                if (!cap.supportedResizing(ir.size, xy, layer->getTransform())) {
                    ALOGE("Unsupported resizing from %dx%d@(%d,%d) --> Target %dx%d with transform %d",
                          ir.size.hori, ir.size.vert, ir.pos.hori, ir.pos.vert,
                          xy.hori, xy.vert, layer->getTransform());
                    return false;
                }
            } else {
                if (!cap.supportedResampling(ir.size, xy, layer->getTransform())) {
                    ALOGE("Unsupported scaling from %dx%d@(%d,%d) --> Target %dx%d with transform %d",
                          ir.size.hori, ir.size.vert, ir.pos.hori, ir.pos.vert,
                          xy.hori, xy.vert, layer->getTransform());
                    return false;
                }
            }
        } else if (rect > xy) {
            ALOGE("Target area %dx%d@(%d,%d) of a layer of %zu layers is out of bound (%dx%d)",
                    rect.size.hori, rect.size.vert, rect.pos.hori, rect.pos.vert,
                    mLayers.size(), xy.hori, xy.vert);
            return false;
        }

        prot = prot || layer->isProtected();
    }

    if (prot && !mCanvas.isProtected()) {
        ALOGE("Target image is not protected while a source layer is protected");
        return false;
    }

    return true;
}

void Acrylic::sortLayers()
{
    std::sort(std::begin(mLayers), std::end(mLayers), [] (auto l1, auto l2) { return l1->getZOrder() < l2->getZOrder(); });
}
