/*
 * Copyright (C) 2017 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 "AST.h"

#include "Coordinator.h"
#include "EnumType.h"
#include "HidlTypeAssertion.h"
#include "Interface.h"
#include "Method.h"
#include "Reference.h"
#include "ScalarType.h"
#include "Scope.h"

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

namespace android {

void AST::generateCppAdapterHeader(Formatter& out) const {
    const std::string klassName = AST::isInterface() ? getInterface()->getAdapterName() : "Atypes";
    const std::string guard = makeHeaderGuard(klassName, true /* indicateGenerated */);

    out << "#ifndef " << guard << "\n";
    out << "#define " << guard << "\n\n";

    if (AST::isInterface()) {
        generateCppPackageInclude(out, mPackage, getInterface()->definedName());

        enterLeaveNamespace(out, true /* enter */);
        out.endl();

        const std::string mockName = getInterface()->fqName().cppName();

        out << "class " << klassName << " : public " << mockName << " ";
        out.block([&] {
            out << "public:\n";
            out << "typedef " << mockName << " Pure;\n";

            out << klassName << "(const ::android::sp<" << mockName << ">& impl);\n";

            generateMethods(out, [&](const Method* method, const Interface* /* interface */) {
                if (method->isHidlReserved()) {
                    return;
                }

                out << "virtual ";
                method->generateCppSignature(out);
                out << " override;\n";
            });
            out << "private:\n";
            out << "::android::sp<" << mockName << "> mImpl;\n";

        }) << ";\n\n";

        enterLeaveNamespace(out, false /* enter */);
    } else {
        out << "// no adapters for types.hal\n";
    }

    out << "#endif // " << guard << "\n";
}

void AST::generateCppAdapterSource(Formatter& out) const {
    const std::string klassName = AST::isInterface() ? getInterface()->getAdapterName() : "Atypes";

    generateCppPackageInclude(out, mPackage, klassName);

    if (AST::isInterface()) {
        out << "#include <hidladapter/HidlBinderAdapter.h>\n";
        generateCppPackageInclude(out, mPackage, getInterface()->definedName());

        std::set<FQName> allImportedNames;
        getAllImportedNames(&allImportedNames);
        for (const auto& item : allImportedNames) {
            if (item.name() == "types") {
                continue;
            }
            generateCppPackageInclude(out, item, item.getInterfaceAdapterName());
        }

        out.endl();

        enterLeaveNamespace(out, true /* enter */);
        out.endl();

        const std::string mockName = getInterface()->fqName().cppName();

        out << klassName << "::" << klassName << "(const ::android::sp<" << mockName
            << ">& impl) : mImpl(impl) {}";

        generateMethods(out, [&](const Method* method, const Interface* /* interface */) {
            generateAdapterMethod(out, method);
        });

        enterLeaveNamespace(out, false /* enter */);
        out.endl();
    } else {
        out << "// no adapters for types.hal\n";
    }
}

void AST::generateAdapterMethod(Formatter& out, const Method* method) const {
    if (method->isHidlReserved()) {
        return;
    }

    const auto adapt = [](Formatter& out, const std::string& var, const Type* type) {
        if (!type->isInterface()) {
            out << var;
            return;
        }

        const Interface* interface = static_cast<const Interface*>(type);
        out << "static_cast<::android::sp<" << interface->fqName().cppName() << ">>("
            << interface->fqName().cppName() << "::castFrom("
            << "::android::hardware::details::adaptWithDefault("
            << "static_cast<::android::sp<" << interface->fqName().cppName() << ">>(" << var
            << "), [&] { return new " << interface->fqName().getInterfaceAdapterFqName().cppName()
            << "(" << var << "); })))";
    };

    const std::string klassName = getInterface()->getAdapterName();

    method->generateCppSignature(out, klassName);
    out.block([&] {
         bool hasCallback = !method->canElideCallback() && !method->results().empty();

         if (hasCallback) {
             out << method->name() << "_cb _hidl_cb_wrapped = [&](";
             method->emitCppResultSignature(out);
             out << ") ";
             out.block([&] {
                 out << "return _hidl_cb(\n";
                 out.indent([&]() {
                     out.join(method->results().begin(), method->results().end(), ",\n",
                              [&](auto arg) { adapt(out, arg->name(), arg->get()); });
                 });
                 out << ");\n";
             });
             out << ";\n";
         }

         out << "auto _hidl_out = mImpl->" << method->name() << "(\n";
         out.indent([&]() {
             out.join(method->args().begin(), method->args().end(), ",\n",
                      [&](auto arg) { adapt(out, arg->name(), arg->get()); });
             if (hasCallback) {
                 if (!method->args().empty()) {
                     out << ",\n";
                 }
                 out << "_hidl_cb_wrapped";
             }
         });
         out << ");\n";

         const auto elidedCallback = method->canElideCallback();
         if (elidedCallback) {
             out.sIf("!_hidl_out.isOkUnchecked()", [&] { out << "return _hidl_out;\n"; });
             out << "return ";
             adapt(out, "_hidl_out", elidedCallback->get());
             out << ";\n";
         } else {
             out << "return _hidl_out;\n";
         }
     }).endl();
}

}  // namespace android
