/*
 * Copyright (C) 2007 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.ide.common.resources;

import com.android.annotations.VisibleForTesting;
import com.android.annotations.VisibleForTesting.Visibility;
import com.android.ide.common.resources.configuration.Configurable;
import com.android.ide.common.resources.configuration.FolderConfiguration;
import com.android.io.IAbstractFile;
import com.android.io.IAbstractFolder;
import com.android.resources.FolderTypeRelationship;
import com.android.resources.ResourceFolderType;
import com.android.resources.ResourceType;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Resource Folder class. Contains list of {@link ResourceFile}s,
 * the {@link FolderConfiguration}, and a link to the {@link IAbstractFolder} object.
 */
public final class ResourceFolder implements Configurable {
    final ResourceFolderType mType;
    final FolderConfiguration mConfiguration;
    IAbstractFolder mFolder;
    List<ResourceFile> mFiles = null;
    Map<String, ResourceFile> mNames = null;
    private final ResourceRepository mRepository;

    /**
     * Creates a new {@link ResourceFolder}
     * @param type The type of the folder
     * @param config The configuration of the folder
     * @param folder The associated {@link IAbstractFolder} object.
     * @param repository The associated {@link ResourceRepository}
     */
    protected ResourceFolder(ResourceFolderType type, FolderConfiguration config,
            IAbstractFolder folder, ResourceRepository repository) {
        mType = type;
        mConfiguration = config;
        mFolder = folder;
        mRepository = repository;
    }

    /**
     * Processes a file and adds it to its parent folder resource.
     *
     * @param file the underlying resource file.
     * @param kind the file change kind.
     * @param context a context object with state for the current update, such
     *            as a place to stash errors encountered
     * @return the {@link ResourceFile} that was created.
     */
    public ResourceFile processFile(IAbstractFile file, ResourceDeltaKind kind,
            ScanningContext context) {
        // look for this file if it's already been created
        ResourceFile resFile = getFile(file, context);

        if (resFile == null) {
            if (kind != ResourceDeltaKind.REMOVED) {
                // create a ResourceFile for it.

                resFile = createResourceFile(file);
                resFile.load(context);

                // add it to the folder
                addFile(resFile);
            }
        } else {
            if (kind == ResourceDeltaKind.REMOVED) {
                removeFile(resFile, context);
            } else {
                resFile.update(context);
            }
        }

        return resFile;
    }

    private ResourceFile createResourceFile(IAbstractFile file) {
        // check if that's a single or multi resource type folder. For now we define this by
        // the number of possible resource type output by files in the folder.
        // We have a special case for layout/menu folders which can also generate IDs.
        // This does
        // not make the difference between several resource types from a single file or
        // the ability to have 2 files in the same folder generating 2 different types of
        // resource. The former is handled by MultiResourceFile properly while we don't
        // handle the latter. If we were to add this behavior we'd have to change this call.
        List<ResourceType> types = FolderTypeRelationship.getRelatedResourceTypes(mType);

        ResourceFile resFile = null;
        if (types.size() == 1) {
            resFile = new SingleResourceFile(file, this);
        } else if (types.contains(ResourceType.LAYOUT)) {
            resFile = new IdGeneratingResourceFile(file, this, ResourceType.LAYOUT);
        } else if (types.contains(ResourceType.MENU)) {
            resFile = new IdGeneratingResourceFile(file, this, ResourceType.MENU);
        } else {
            resFile = new MultiResourceFile(file, this);
        }
        return resFile;
    }

    /**
     * Adds a {@link ResourceFile} to the folder.
     * @param file The {@link ResourceFile}.
     */
    @VisibleForTesting(visibility=Visibility.PROTECTED)
    public void addFile(ResourceFile file) {
        if (mFiles == null) {
            int initialSize = 16;
            if (mRepository.isFrameworkRepository()) {
                String name = mFolder.getName();
                // Pick some reasonable initial sizes for framework data structures
                // since they are typically (a) large and (b) their sizes are roughly known
                // in advance
                switch (mType) {
                    case DRAWABLE: {
                        // See if it's one of the -mdpi, -hdpi etc folders which
                        // are large (~1250 items)
                        int index = name.indexOf('-');
                        if (index == -1) {
                            initialSize = 230; // "drawable" folder
                        } else {
                            index = name.indexOf('-', index + 1);
                            if (index == -1) {
                                // One of the "drawable-<density>" folders
                                initialSize = 1260;
                            } else {
                                // "drawable-sw600dp-hdpi" etc
                                initialSize = 30;
                            }
                        }
                        break;
                    }
                    case LAYOUT: {
                        // The main layout folder has about ~185 layouts in it;
                        // the others are small
                        if (name.indexOf('-') == -1) {
                            initialSize = 200;
                        }
                        break;
                    }
                    case VALUES: {
                        if (name.indexOf('-') == -1) {
                            initialSize = 32;
                        } else {
                            initialSize = 4;
                        }
                        break;
                    }
                    case ANIM: initialSize = 85; break;
                    case COLOR: initialSize = 32; break;
                    case RAW: initialSize = 4; break;
                    default:
                        // Stick with the 16 default
                        break;
                }
            }

            mFiles = new ArrayList<ResourceFile>(initialSize);
            mNames = new HashMap<String, ResourceFile>(initialSize, 2.0f);
        }

        mFiles.add(file);
        mNames.put(file.getFile().getName(), file);
    }

    protected void removeFile(ResourceFile file, ScanningContext context) {
        file.dispose(context);
        mFiles.remove(file);
        mNames.remove(file.getFile().getName());
    }

    protected void dispose(ScanningContext context) {
        if (mFiles != null) {
            for (ResourceFile file : mFiles) {
                file.dispose(context);
            }

            mFiles.clear();
            mNames.clear();
        }
    }

    /**
     * Returns the {@link IAbstractFolder} associated with this object.
     */
    public IAbstractFolder getFolder() {
        return mFolder;
    }

    /**
     * Returns the {@link ResourceFolderType} of this object.
     */
    public ResourceFolderType getType() {
        return mType;
    }

    public ResourceRepository getRepository() {
        return mRepository;
    }

    /**
     * Returns the list of {@link ResourceType}s generated by the files inside this folder.
     */
    public Collection<ResourceType> getResourceTypes() {
        ArrayList<ResourceType> list = new ArrayList<ResourceType>();

        if (mFiles != null) {
            for (ResourceFile file : mFiles) {
                Collection<ResourceType> types = file.getResourceTypes();

                // loop through those and add them to the main list,
                // if they are not already present
                for (ResourceType resType : types) {
                    if (list.indexOf(resType) == -1) {
                        list.add(resType);
                    }
                }
            }
        }

        return list;
    }

    @Override
    public FolderConfiguration getConfiguration() {
        return mConfiguration;
    }

    /**
     * Returns whether the folder contains a file with the given name.
     * @param name the name of the file.
     */
    public boolean hasFile(String name) {
        if (mNames != null && mNames.containsKey(name)) {
            return true;
        }

        // Note: mNames.containsKey(name) is faster, but doesn't give the same result; this
        // method seems to be called on this ResourceFolder before it has been processed,
        // so we need to use the file system check instead:
        return mFolder.hasFile(name);
    }

    /**
     * Returns the {@link ResourceFile} matching a {@link IAbstractFile} object.
     *
     * @param file The {@link IAbstractFile} object.
     * @param context a context object with state for the current update, such
     *            as a place to stash errors encountered
     * @return the {@link ResourceFile} or null if no match was found.
     */
    private ResourceFile getFile(IAbstractFile file, ScanningContext context) {
        assert mFolder.equals(file.getParentFolder());

        if (mNames != null) {
            ResourceFile resFile = mNames.get(file.getName());
            if (resFile != null) {
                return resFile;
            }
        }

        // If the file actually exists, the resource folder  may not have been
        // scanned yet; add it lazily
        if (file.exists()) {
            ResourceFile resFile = createResourceFile(file);
            resFile.load(context);
            addFile(resFile);
            return resFile;
        }

        return null;
    }

    /**
     * Returns the {@link ResourceFile} matching a given name.
     * @param filename The name of the file to return.
     * @return the {@link ResourceFile} or <code>null</code> if no match was found.
     */
    public ResourceFile getFile(String filename) {
        if (mNames != null) {
            ResourceFile resFile = mNames.get(filename);
            if (resFile != null) {
                return resFile;
            }
        }

        // If the file actually exists, the resource folder  may not have been
        // scanned yet; add it lazily
        IAbstractFile file = mFolder.getFile(filename);
        if (file != null && file.exists()) {
            ResourceFile resFile = createResourceFile(file);
            resFile.load(new ScanningContext(mRepository));
            addFile(resFile);
            return resFile;
        }

        return null;
    }

    /**
     * Returns whether a file in the folder is generating a resource of a specified type.
     * @param type The {@link ResourceType} being looked up.
     */
    public boolean hasResources(ResourceType type) {
        // Check if the folder type is able to generate resource of the type that was asked.
        // this is a first check to avoid going through the files.
        List<ResourceFolderType> folderTypes = FolderTypeRelationship.getRelatedFolders(type);

        boolean valid = false;
        for (ResourceFolderType rft : folderTypes) {
            if (rft == mType) {
                valid = true;
                break;
            }
        }

        if (valid) {
            if (mFiles != null) {
                for (ResourceFile f : mFiles) {
                    if (f.hasResources(type)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    @Override
    public String toString() {
        return mFolder.toString();
    }
}
