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

#include "java/ProguardRules.h"
#include "util/Util.h"

#include <memory>
#include <string>

namespace aapt {
namespace proguard {

class BaseVisitor : public xml::Visitor {
public:
    BaseVisitor(const Source& source, KeepSet* keepSet) : mSource(source), mKeepSet(keepSet) {
    }

    virtual void visit(xml::Text*) override {};

    virtual void visit(xml::Namespace* node) override {
        for (const auto& child : node->children) {
            child->accept(this);
        }
    }

    virtual void visit(xml::Element* node) override {
        if (!node->namespaceUri.empty()) {
            Maybe<std::u16string> maybePackage = util::extractPackageFromNamespace(
                    node->namespaceUri);
            if (maybePackage) {
                // This is a custom view, let's figure out the class name from this.
                std::u16string package = maybePackage.value() + u"." + node->name;
                if (util::isJavaClassName(package)) {
                    addClass(node->lineNumber, package);
                }
            }
        } else if (util::isJavaClassName(node->name)) {
            addClass(node->lineNumber, node->name);
        }

        for (const auto& child: node->children) {
            child->accept(this);
        }
    }

protected:
    void addClass(size_t lineNumber, const std::u16string& className) {
        mKeepSet->addClass(Source(mSource.path, lineNumber), className);
    }

    void addMethod(size_t lineNumber, const std::u16string& methodName) {
        mKeepSet->addMethod(Source(mSource.path, lineNumber), methodName);
    }

private:
    Source mSource;
    KeepSet* mKeepSet;
};

struct LayoutVisitor : public BaseVisitor {
    LayoutVisitor(const Source& source, KeepSet* keepSet) : BaseVisitor(source, keepSet) {
    }

    virtual void visit(xml::Element* node) override {
        bool checkClass = false;
        bool checkName = false;
        if (node->namespaceUri.empty()) {
            checkClass = node->name == u"view" || node->name == u"fragment";
        } else if (node->namespaceUri == xml::kSchemaAndroid) {
            checkName = node->name == u"fragment";
        }

        for (const auto& attr : node->attributes) {
            if (checkClass && attr.namespaceUri.empty() && attr.name == u"class" &&
                    util::isJavaClassName(attr.value)) {
                addClass(node->lineNumber, attr.value);
            } else if (checkName && attr.namespaceUri == xml::kSchemaAndroid &&
                    attr.name == u"name" && util::isJavaClassName(attr.value)) {
                addClass(node->lineNumber, attr.value);
            } else if (attr.namespaceUri == xml::kSchemaAndroid && attr.name == u"onClick") {
                addMethod(node->lineNumber, attr.value);
            }
        }

        BaseVisitor::visit(node);
    }
};

struct XmlResourceVisitor : public BaseVisitor {
    XmlResourceVisitor(const Source& source, KeepSet* keepSet) : BaseVisitor(source, keepSet) {
    }

    virtual void visit(xml::Element* node) override {
        bool checkFragment = false;
        if (node->namespaceUri.empty()) {
            checkFragment = node->name == u"PreferenceScreen" || node->name == u"header";
        }

        if (checkFragment) {
            xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, u"fragment");
            if (attr && util::isJavaClassName(attr->value)) {
                addClass(node->lineNumber, attr->value);
            }
        }

        BaseVisitor::visit(node);
    }
};

struct TransitionVisitor : public BaseVisitor {
    TransitionVisitor(const Source& source, KeepSet* keepSet) : BaseVisitor(source, keepSet) {
    }

    virtual void visit(xml::Element* node) override {
        bool checkClass = node->namespaceUri.empty() &&
                (node->name == u"transition" || node->name == u"pathMotion");
        if (checkClass) {
            xml::Attribute* attr = node->findAttribute({}, u"class");
            if (attr && util::isJavaClassName(attr->value)) {
                addClass(node->lineNumber, attr->value);
            }
        }

        BaseVisitor::visit(node);
    }
};

struct ManifestVisitor : public BaseVisitor {
    ManifestVisitor(const Source& source, KeepSet* keepSet) : BaseVisitor(source, keepSet) {
    }

    virtual void visit(xml::Element* node) override {
        if (node->namespaceUri.empty()) {
            bool getName = false;
            if (node->name == u"manifest") {
                xml::Attribute* attr = node->findAttribute({}, u"package");
                if (attr) {
                    mPackage = attr->value;
                }
            } else if (node->name == u"application") {
                getName = true;
                xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, u"backupAgent");
                if (attr) {
                    Maybe<std::u16string> result = util::getFullyQualifiedClassName(mPackage,
                                                                                    attr->value);
                    if (result) {
                        addClass(node->lineNumber, result.value());
                    }
                }
            } else if (node->name == u"activity" || node->name == u"service" ||
                    node->name == u"receiver" || node->name == u"provider" ||
                    node->name == u"instrumentation") {
                getName = true;
            }

            if (getName) {
                xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, u"name");
                if (attr) {
                    Maybe<std::u16string> result = util::getFullyQualifiedClassName(mPackage,
                                                                                    attr->value);
                    if (result) {
                        addClass(node->lineNumber, result.value());
                    }
                }
            }
        }
        BaseVisitor::visit(node);
    }

    std::u16string mPackage;
};

bool collectProguardRulesForManifest(const Source& source, XmlResource* res, KeepSet* keepSet) {
    ManifestVisitor visitor(source, keepSet);
    if (res->root) {
        res->root->accept(&visitor);
        return true;
    }
    return false;
}

bool collectProguardRules(const Source& source, XmlResource* res, KeepSet* keepSet) {
    if (!res->root) {
        return false;
    }

    switch (res->file.name.type) {
        case ResourceType::kLayout: {
            LayoutVisitor visitor(source, keepSet);
            res->root->accept(&visitor);
            break;
        }

        case ResourceType::kXml: {
            XmlResourceVisitor visitor(source, keepSet);
            res->root->accept(&visitor);
            break;
        }

        case ResourceType::kTransition: {
            TransitionVisitor visitor(source, keepSet);
            res->root->accept(&visitor);
            break;
        }

        default:
            break;
    }
    return true;
}

bool writeKeepSet(std::ostream* out, const KeepSet& keepSet) {
    for (const auto& entry : keepSet.mKeepSet) {
        for (const Source& source : entry.second) {
            *out << "// Referenced at " << source << "\n";
        }
        *out << "-keep class " << entry.first << " { <init>(...); }\n" << std::endl;
    }

    for (const auto& entry : keepSet.mKeepMethodSet) {
        for (const Source& source : entry.second) {
            *out << "// Referenced at " << source << "\n";
        }
        *out << "-keepclassmembers class * { *** " << entry.first << "(...); }\n" << std::endl;
    }
    return true;
}

} // namespace proguard
} // namespace aapt
