/*
 * 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 "Scope.h"

#include "Annotation.h"
#include "ConstantExpression.h"
#include "Interface.h"

#include <android-base/logging.h>
#include <hidl-util/Formatter.h>
#include <algorithm>
#include <iostream>
#include <vector>

namespace android {

Scope::Scope(const char* localName, const FQName& fullName, const Location& location, Scope* parent)
    : NamedType(localName, fullName, location, parent) {}
Scope::~Scope(){}

void Scope::addType(NamedType* type) {
    size_t index = mTypes.size();
    mTypes.push_back(type);
    mTypeIndexByName[type->localName()] = index;
}

status_t Scope::validateUniqueNames() const {
    for (const auto* type : mTypes) {
        if (mTypes[mTypeIndexByName.at(type->localName())] != type) {
            std::cerr << "ERROR: A type named '" << type->localName()
                      << "' is already declared in the scope at " << type->location() << "\n";
            return UNKNOWN_ERROR;
        }
    }
    return OK;
}

NamedType *Scope::lookupType(const FQName &fqName) const {
    CHECK(fqName.package().empty() && fqName.version().empty());
    if (!fqName.valueName().empty()) {
        LOG(WARNING) << fqName.string() << " does not refer to a type.";
        return nullptr;
    }
    std::vector<std::string> names = fqName.names();
    CHECK_GT(names.size(), 0u);
    auto it = mTypeIndexByName.find(names[0]);

    if (it == mTypeIndexByName.end()) {
        return nullptr;
    }

    NamedType *outerType = mTypes[it->second];
    if (names.size() == 1) {
        return outerType;
    }
    if (!outerType->isScope()) {
        // more than one names, but the first name is not a scope
        return nullptr;
    }
    Scope *outerScope = static_cast<Scope *>(outerType);
    // *slowly* pop first element
    names.erase(names.begin());
    FQName innerName(names);
    return outerScope->lookupType(innerName);
}

LocalIdentifier *Scope::lookupIdentifier(const std::string & /*name*/) const {
    return NULL;
}

bool Scope::isScope() const {
    return true;
}

Interface *Scope::getInterface() const {
    if (mTypes.size() == 1 && mTypes[0]->isInterface()) {
        return static_cast<Interface *>(mTypes[0]);
    }

    return NULL;
}

bool Scope::containsInterfaces() const {
    for (const NamedType *type : mTypes) {
        if (type->isInterface()) {
            return true;
        }
    }

    return false;
}

const std::vector<Annotation*>& Scope::annotations() const {
    return mAnnotations;
}

void Scope::setAnnotations(std::vector<Annotation*>* annotations) {
    CHECK(mAnnotations.empty());
    CHECK(annotations != nullptr);
    mAnnotations = *annotations;
}

std::vector<const Type*> Scope::getDefinedTypes() const {
    std::vector<const Type*> ret;
    ret.insert(ret.end(), mTypes.begin(), mTypes.end());
    return ret;
}

std::vector<const ConstantExpression*> Scope::getConstantExpressions() const {
    std::vector<const ConstantExpression*> ret;
    for (const auto* annotation : mAnnotations) {
        const auto& retAnnotation = annotation->getConstantExpressions();
        ret.insert(ret.end(), retAnnotation.begin(), retAnnotation.end());
    }
    return ret;
}

void Scope::topologicalReorder(const std::unordered_map<const Type*, size_t>& reversedOrder) {
    auto less = [&](const Type* lhs, const Type* rhs) {
        return reversedOrder.at(lhs) < reversedOrder.at(rhs);
    };

    if (std::is_sorted(mTypes.begin(), mTypes.end(), less)) return;

    mTypeOrderChanged = true;
    std::sort(mTypes.begin(), mTypes.end(), less);

    for (size_t i = 0; i != mTypes.size(); ++i) {
        mTypeIndexByName.at(mTypes[i]->localName()) = i;
    }
}

status_t Scope::forEachType(const std::function<status_t(Type *)> &func) const {
    for (size_t i = 0; i < mTypes.size(); ++i) {
        status_t err = func(mTypes[i]);

        if (err != OK) {
            return err;
        }
    }

    return OK;
}

status_t Scope::emitTypeDeclarations(Formatter &out) const {
    if (mTypes.empty()) return OK;

    out << "// Forward declaration for forward reference support:\n";
    forEachType([&](Type* type) {
        type->emitTypeForwardDeclaration(out);
        return OK;
    });
    out << "\n";

    if (mTypeOrderChanged) {
        out << "// Order of inner types was changed for forward reference support.\n\n";
    }
    return forEachType([&](Type* type) {
        return type->emitTypeDeclarations(out);
    });
}

status_t Scope::emitGlobalTypeDeclarations(Formatter &out) const {
    return forEachType([&](Type *type) {
        return type->emitGlobalTypeDeclarations(out);
    });
}

status_t Scope::emitGlobalHwDeclarations(Formatter &out) const {
    return forEachType([&](Type *type) {
        return type->emitGlobalHwDeclarations(out);
    });
}

status_t Scope::emitJavaTypeDeclarations(
        Formatter &out, bool atTopLevel) const {
    if (mTypeOrderChanged) {
        out << "// Order of inner types was changed for forward reference support.\n\n";
    }
    return forEachType([&](Type *type) {
        return type->emitJavaTypeDeclarations(out, atTopLevel);
    });
}

status_t Scope::emitTypeDefinitions(Formatter& out, const std::string& prefix) const {
    return forEachType([&](Type *type) {
        return type->emitTypeDefinitions(out, prefix);
    });
}

const std::vector<NamedType *> &Scope::getSubTypes() const {
    return mTypes;
}

status_t Scope::emitVtsTypeDeclarations(Formatter &out) const {
    return forEachType([&](Type *type) {
        return type->emitVtsTypeDeclarations(out);
    });
}

bool Scope::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
    for (const auto &type : mTypes) {
        if (!type->isJavaCompatible(visited)) {
            return false;
        }
    }
    return Type::deepIsJavaCompatible(visited);
}

void Scope::appendToExportedTypesVector(
        std::vector<const Type *> *exportedTypes) const {
    forEachType([&](Type *type) {
        type->appendToExportedTypesVector(exportedTypes);
        return OK;
    });
}

////////////////////////////////////////

RootScope::RootScope(const char* localName, const FQName& fullName, const Location& location,
                     Scope* parent)
    : Scope(localName, fullName, location, parent) {}
RootScope::~RootScope() {}

std::string RootScope::typeName() const {
    return "(root scope)";
}

status_t RootScope::validate() const {
    CHECK(annotations().empty());
    return Scope::validate();
}

////////////////////////////////////////

LocalIdentifier::LocalIdentifier(){}
LocalIdentifier::~LocalIdentifier(){}

bool LocalIdentifier::isEnumValue() const {
    return false;
}

const LocalIdentifier* LocalIdentifier::resolve() const {
    return this;
}

LocalIdentifier* LocalIdentifier::resolve() {
    return this;
}

ConstantExpression* LocalIdentifier::constExpr() const {
    return nullptr;
}

}  // namespace android

