/*
 * 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.
 */

package com.android.databinding.store;

import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;

import com.android.databinding.util.L;
import com.android.databinding.util.ParserHelper;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

/**
 * This is a serializable class that can keep the result of parsing layout files.
 */
public class ResourceBundle implements Serializable {

    private String mAppPackage;

    private HashMap<String, List<LayoutFileBundle>> mLayoutBundles
            = new HashMap<String, List<LayoutFileBundle>>();

    public ResourceBundle(String appPackage) {
        mAppPackage = appPackage;
    }

    public void addLayoutBundle(LayoutFileBundle bundle, int layoutId) {
        Preconditions.checkArgument(bundle.mFileName != null, "File bundle must have a name");
        if (!mLayoutBundles.containsKey(bundle.mFileName)) {
            mLayoutBundles.put(bundle.mFileName, new ArrayList<LayoutFileBundle>());
        }
        bundle.mLayoutId = layoutId;
        final List<LayoutFileBundle> bundles = mLayoutBundles.get(bundle.mFileName);
        for (LayoutFileBundle existing : bundles) {
            if (existing.equals(bundle)) {
                L.d("skipping layout bundle %s because it already exists.", bundle);
                return;
            }
        }
        L.d("adding bundle %s", bundle);
        bundles.add(bundle);
    }

    public HashMap<String, List<LayoutFileBundle>> getLayoutBundles() {
        return mLayoutBundles;
    }

    public String getAppPackage() {
        return mAppPackage;
    }

    public void validateMultiResLayouts() {
        final Iterable<Map.Entry<String, List<LayoutFileBundle>>> multiResLayouts = Iterables
                .filter(mLayoutBundles.entrySet(),
                        new Predicate<Map.Entry<String, List<LayoutFileBundle>>>() {
                            @Override
                            public boolean apply(Map.Entry<String, List<LayoutFileBundle>> input) {
                                return input.getValue().size() > 1;
                            }
                        });

        for (Map.Entry<String, List<LayoutFileBundle>> bundles : multiResLayouts) {
            // validate all ids are in correct view types
            // and all variables have the same name
            Map<String, String> variableTypes = new HashMap<String, String>();
            Map<String, String> importTypes = new HashMap<String, String>();

            for (LayoutFileBundle bundle : bundles.getValue()) {
                bundle.mHasVariations = true;
                for (Map.Entry<String, String> variable : bundle.mVariables.entrySet()) {
                    String existing = variableTypes.get(variable.getKey());
                    Preconditions
                            .checkState(existing == null || existing.equals(variable.getValue()),
                                    "inconsistent variable types for %s for layout %s",
                                    variable.getKey(), bundle.mFileName);
                    variableTypes.put(variable.getKey(), variable.getValue());
                }
                for (Map.Entry<String, String> userImport : bundle.mImports.entrySet()) {
                    String existing = importTypes.get(userImport.getKey());
                    Preconditions
                            .checkState(existing == null || existing.equals(userImport.getValue()),
                                    "inconsistent variable types for %s for layout %s",
                                    userImport.getKey(), bundle.mFileName);
                    importTypes.put(userImport.getKey(), userImport.getValue());
                }
            }

            for (LayoutFileBundle bundle : bundles.getValue()) {
                // now add missing ones to each to ensure they can be referenced
                L.d("checking for missing variables in %s / %s", bundle.mFileName,
                        bundle.mConfigName);
                for (Map.Entry<String, String> variable : variableTypes.entrySet()) {
                    if (!bundle.mVariables.containsKey(variable.getKey())) {
                        bundle.mVariables.put(variable.getKey(), variable.getValue());
                        L.d("adding missing variable %s to %s / %s", variable.getKey(),
                                bundle.mFileName, bundle.mConfigName);
                    }
                }
                for (Map.Entry<String, String> userImport : importTypes.entrySet()) {
                    if (!bundle.mImports.containsKey(userImport.getKey())) {
                        bundle.mImports.put(userImport.getKey(), userImport.getValue());
                        L.d("adding missing import %s to %s / %s", userImport.getKey(),
                                bundle.mFileName, bundle.mConfigName);
                    }
                }
            }

            Set<String> includeBindingIds = new HashSet<String>();
            Set<String> viewBindingIds = new HashSet<String>();
            Map<String, String> viewTypes = new HashMap<String, String>();
            L.d("validating ids for %s", bundles.getKey());
            for (LayoutFileBundle bundle : bundles.getValue()) {
                for (BindingTargetBundle target : bundle.mBindingTargetBundles) {
                    L.d("checking %s %s %s", target.getId(), target.mFullClassName, target.isBinder());
                    if (target.isBinder()) {
                        Preconditions.checkState(!viewBindingIds.contains(target.mFullClassName),
                                "Cannot use the same id for a View and an include tag. Error in "
                                        + "file %s / %s", bundle.mFileName, bundle.mConfigName);
                        includeBindingIds.add(target.mFullClassName);
                    } else {
                        Preconditions.checkState(!includeBindingIds.contains(target.mFullClassName),
                                "Cannot use the same id for a View and an include tag. Error in "
                                        + "file %s / %s", bundle.mFileName, bundle.mConfigName);
                        viewBindingIds.add(target.mFullClassName);
                    }
                    String existingType = viewTypes.get(target.mId);
                    if (existingType == null) {
                        L.d("assigning %s as %s", target.getId(), target.mFullClassName);
                        viewTypes.put(target.mId, target.mFullClassName);
                    } else if (!existingType.equals(target.mFullClassName)) {
                        if (target.isBinder()) {
                            L.d("overriding %s as base binder", target.getId());
                            viewTypes.put(target.mId,
                                    "com.android.databinding.library.ViewDataBinding");
                        } else {
                            L.d("overriding %s as base view", target.getId());
                            viewTypes.put(target.mId, "android.view.View");
                        }
                    }
                }
            }

            for (LayoutFileBundle bundle : bundles.getValue()) {
                for (Map.Entry<String, String> viewType : viewTypes.entrySet()) {
                    BindingTargetBundle target = bundle.getBindingTargetById(viewType.getKey());
                    if (target == null) {
                        bundle.createBindingTarget(viewType.getKey(), viewType.getValue(), false,
                                null, null);
                    } else {
                        L.d("setting interface type on %s (%s) as %s", target.mId, target.mFullClassName, viewType.getValue());
                        target.setInterfaceType(viewType.getValue());
                    }
                }
            }
        }
        // assign class names to each
        for (Map.Entry<String, List<LayoutFileBundle>> entry : mLayoutBundles.entrySet()) {
            for (LayoutFileBundle bundle : entry.getValue()) {
                final String configName;
                if (bundle.hasVariations()) {
                    // append configuration specifiers.
                    final String parentFileName = bundle.mDirectory;
                    L.d("parent file for %s is %s", bundle.getFileName(), parentFileName);
                    if ("layout".equals(parentFileName)) {
                        configName = "";
                    } else {
                        configName = ParserHelper.INSTANCE$.toClassName(parentFileName.substring("layout-".length()));
                    }
                } else {
                    configName = "";
                }
                bundle.mConfigName = configName;
            }
        }
    }

    @XmlAccessorType(XmlAccessType.NONE)
    @XmlRootElement(name="Layout")
    public static class LayoutFileBundle implements Serializable {
        @XmlAttribute(name="layoutId", required = true)
        public int mLayoutId;
        @XmlAttribute(name="layout", required = true)
        public String mFileName;
        @XmlAttribute(name="modulePackage", required = true)
        public String mModulePackage;
        private String mConfigName;

        @XmlAttribute(name="directory", required = true)
        public String mDirectory;
        public boolean mHasVariations;

        @XmlElement(name="Variables")
        @XmlJavaTypeAdapter(NameTypeAdapter.class)
        public Map<String, String> mVariables = new HashMap<String, String>();

        @XmlElement(name="Imports")
        @XmlJavaTypeAdapter(NameTypeAdapter.class)
        public Map<String, String> mImports = new HashMap<String, String>();

        @XmlElementWrapper(name="Targets")
        @XmlElement(name="Target")
        public List<BindingTargetBundle> mBindingTargetBundles = new ArrayList<BindingTargetBundle>();

        // for XML binding
        public LayoutFileBundle() {
        }

        public LayoutFileBundle(String fileName, int layoutId, String directory,
                String modulePackage) {
            mFileName = fileName;
            mLayoutId = layoutId;
            mDirectory = directory;
            mModulePackage = modulePackage;
        }

        public void addVariable(String name, String type) {
            mVariables.put(name, type);
        }

        public void addImport(String alias, String type) {
            mImports.put(alias, type);
        }

        public BindingTargetBundle createBindingTarget(String id, String fullClassName,
                boolean used, String tag, String originalTag) {
            BindingTargetBundle target = new BindingTargetBundle(id, fullClassName, used, tag,
                    originalTag);
            mBindingTargetBundles.add(target);
            return target;
        }

        public boolean isEmpty() {
            return mVariables.isEmpty() && mImports.isEmpty() && mBindingTargetBundles.isEmpty();
        }

        public BindingTargetBundle getBindingTargetById(String key) {
            for (BindingTargetBundle target : mBindingTargetBundles) {
                if (key.equals(target.mId)) {
                    return target;
                }
            }
            return null;
        }

        public int getLayoutId() {
            return mLayoutId;
        }

        public String getFileName() {
            return mFileName;
        }

        public String getConfigName() {
            return mConfigName;
        }

        public String getDirectory() {
            return mDirectory;
        }

        public boolean hasVariations() {
            return mHasVariations;
        }

        public Map<String, String> getVariables() {
            return mVariables;
        }

        public Map<String, String> getImports() {
            return mImports;
        }

        public List<BindingTargetBundle> getBindingTargetBundles() {
            return mBindingTargetBundles;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            LayoutFileBundle bundle = (LayoutFileBundle) o;

            if (mConfigName != null ? !mConfigName.equals(bundle.mConfigName)
                    : bundle.mConfigName != null) {
                return false;
            }
            if (mDirectory != null ? !mDirectory.equals(bundle.mDirectory)
                    : bundle.mDirectory != null) {
                return false;
            }
            if (mFileName != null ? !mFileName.equals(bundle.mFileName)
                    : bundle.mFileName != null) {
                return false;
            }

            return true;
        }

        @Override
        public int hashCode() {
            int result = mFileName != null ? mFileName.hashCode() : 0;
            result = 31 * result + (mConfigName != null ? mConfigName.hashCode() : 0);
            result = 31 * result + (mDirectory != null ? mDirectory.hashCode() : 0);
            return result;
        }

        @Override
        public String toString() {
            return "LayoutFileBundle{" +
                    "mHasVariations=" + mHasVariations +
                    ", mDirectory='" + mDirectory + '\'' +
                    ", mConfigName='" + mConfigName + '\'' +
                    ", mModulePackage='" + mModulePackage + '\'' +
                    ", mFileName='" + mFileName + '\'' +
                    ", mLayoutId=" + mLayoutId +
                    '}';
        }

        public String getModulePackage() {
            return mModulePackage;
        }
    }

    @XmlAccessorType(XmlAccessType.NONE)
    public static class MarshalledNameType {
        @XmlAttribute(name="type", required = true)
        public String type;

        @XmlAttribute(name="name", required = true)
        public String name;
    }

    public static class MarshalledMapType {
        public List<MarshalledNameType> entries;
    }

    @XmlAccessorType(XmlAccessType.NONE)
    public static class BindingTargetBundle implements Serializable {
        // public for XML serialization

        @XmlAttribute(name="id")
        public String mId;
        @XmlAttribute(name="tag", required = true)
        public String mTag;
        @XmlAttribute(name="originalTag")
        public String mOriginalTag;
        @XmlAttribute(name="boundClass", required = true)
        public String mFullClassName;
        public boolean mUsed = true;
        @XmlElementWrapper(name="Expressions")
        @XmlElement(name="Expression")
        public List<BindingBundle> mBindingBundleList = new ArrayList<BindingBundle>();
        @XmlAttribute(name="include")
        public String mIncludedLayout;
        private String mInterfaceType;

        // For XML serialization
        public BindingTargetBundle() {}

        public BindingTargetBundle(String id, String fullClassName, boolean used,
                String tag, String originalTag) {
            mId = id;
            mFullClassName = fullClassName;
            mUsed = used;
            mTag = tag;
            mOriginalTag = originalTag;
        }

        public void addBinding(String name, String expr) {
            mBindingBundleList.add(new BindingBundle(name, expr));
        }

        public void setIncludedLayout(String includedLayout) {
            mIncludedLayout = includedLayout;
        }

        public String getIncludedLayout() {
            return mIncludedLayout;
        }

        public boolean isBinder() {
            return mIncludedLayout != null;
        }

        public void setInterfaceType(String interfaceType) {
            mInterfaceType = interfaceType;
        }

        public String getId() {
            return mId;
        }

        public String getTag() {
            return mTag;
        }

        public String getOriginalTag() {
            return mOriginalTag;
        }

        public String getFullClassName() {
            return mFullClassName;
        }

        public boolean isUsed() {
            return mUsed;
        }

        public List<BindingBundle> getBindingBundleList() {
            return mBindingBundleList;
        }

        public String getInterfaceType() {
            return mInterfaceType;
        }

        @XmlAccessorType(XmlAccessType.NONE)
        public static class BindingBundle implements Serializable {

            private String mName;
            private String mExpr;

            public BindingBundle() {}

            public BindingBundle(String name, String expr) {
                mName = name;
                mExpr = expr;
            }

            @XmlAttribute(name="attribute", required=true)
            public String getName() {
                return mName;
            }

            @XmlAttribute(name="text", required=true)
            public String getExpr() {
                return mExpr;
            }

            public void setName(String name) {
                mName = name;
            }

            public void setExpr(String expr) {
                mExpr = expr;
            }
        }
    }

    private final static class NameTypeAdapter
            extends XmlAdapter<MarshalledMapType, Map<String, String>> {

        @Override
        public HashMap<String, String> unmarshal(MarshalledMapType v) throws Exception {
            HashMap<String, String> map = new HashMap<String, String>();
            if (v.entries != null) {
                for (MarshalledNameType entry : v.entries) {
                    map.put(entry.name, entry.type);
                }
            }
            return map;
        }

        @Override
        public MarshalledMapType marshal(Map<String, String> v) throws Exception {
            if (v.isEmpty()) {
                return null;
            }
            MarshalledMapType marshalled = new MarshalledMapType();
            marshalled.entries = new ArrayList<MarshalledNameType>();
            for (String name : v.keySet()) {
                MarshalledNameType nameType = new MarshalledNameType();
                nameType.name = name;
                nameType.type = v.get(name);
                marshalled.entries.add(nameType);
            }
            return marshalled;
        }
    }
}
