/*
 * Copyright (C) 2014 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.builder.internal.compiler;

import com.android.annotations.NonNull;
import com.android.builder.core.AndroidBuilder;
import com.android.builder.core.DexOptions;
import com.android.ide.common.internal.CommandLineRunner;
import com.android.ide.common.internal.LoggedErrorException;
import com.android.sdklib.BuildToolInfo;
import com.android.sdklib.repository.FullRevision;
import com.android.utils.Pair;
import com.google.common.io.Files;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import java.io.File;
import java.io.IOException;

/**
 * Pre Dexing cache.
 *
 * Since we cannot yet have a single task for each library that needs to be pre-dexed (because
 * there is no task-level parallelization), this class allows reusing the output of the pre-dexing
 * of a library in a project to write the output of the pre-dexing of the same library in
 * a different project.
 *
 * Because different project could use different build-tools, both the library to pre-dex and the
 * version of the build tools are used as keys in the cache.
 *
 * The API is fairly simple, just call {@link #preDexLibrary(java.io.File, java.io.File, com.android.builder.core.DexOptions, com.android.sdklib.BuildToolInfo, boolean, com.android.ide.common.internal.CommandLineRunner)}
 *
 * The call will be blocking until the pre-dexing happened, either through actual pre-dexing or
 * through copying the output of a previous pre-dex run.
 *
 * After a build a call to {@link #clear(java.io.File, com.android.utils.ILogger)} with a file
 * will allow saving the known pre-dexed libraries for future reuse.
 */
public class PreDexCache extends PreProcessCache<DexKey> {

    private static final String ATTR_JUMBO_MODE = "jumboMode";

    private static final PreDexCache sSingleton = new PreDexCache();

    public static PreDexCache getCache() {
        return sSingleton;
    }

    @Override
    @NonNull
    protected KeyFactory<DexKey> getKeyFactory() {
        return new KeyFactory<DexKey>() {
            @Override
            public DexKey of(@NonNull File sourceFile, @NonNull FullRevision revision,
                    @NonNull NamedNodeMap attrMap) {
                return DexKey.of(sourceFile, revision,
                        Boolean.parseBoolean(attrMap.getNamedItem(ATTR_JUMBO_MODE).getNodeValue()));
            }
        };
    }

    /**
     * Pre-dex a given library to a given output with a specific version of the build-tools.
     * @param inputFile the jar to pre-dex
     * @param outFile the output file.
     * @param dexOptions the dex options to run pre-dex
     * @param buildToolInfo the build tools info
     * @param verbose verbose flag
     * @param commandLineRunner the command line runner.
     * @throws IOException
     * @throws LoggedErrorException
     * @throws InterruptedException
     */
    public void preDexLibrary(
            @NonNull File inputFile,
            @NonNull File outFile,
            @NonNull DexOptions dexOptions,
            @NonNull BuildToolInfo buildToolInfo,
            boolean verbose,
            @NonNull CommandLineRunner commandLineRunner)
            throws IOException, LoggedErrorException, InterruptedException {

        DexKey itemKey = DexKey.of(inputFile, buildToolInfo.getRevision(), dexOptions.getJumboMode());

        Pair<Item, Boolean> pair = getItem(itemKey, inputFile, outFile);

        // if this is a new item
        if (pair.getSecond()) {
            try {
                // haven't process this file yet so do it and record it.
                AndroidBuilder.preDexLibrary(inputFile, outFile, dexOptions, buildToolInfo,
                        verbose, commandLineRunner);

                incrementMisses();
            } catch (IOException exception) {
                // in case of error, delete (now obsolete) output file
                outFile.delete();
                // and rethrow the error
                throw exception;
            } catch (LoggedErrorException exception) {
                // in case of error, delete (now obsolete) output file
                outFile.delete();
                // and rethrow the error
                throw exception;
            } catch (InterruptedException exception) {
                // in case of error, delete (now obsolete) output file
                outFile.delete();
                // and rethrow the error
                throw exception;
            } finally {
                // enable other threads to use the output of this pre-dex.
                // if something was thrown they'll handle the missing output file.
                pair.getFirst().getLatch().countDown();
            }
        } else {
            // wait until the file is pre-dexed by the first thread.
            pair.getFirst().getLatch().await();

            // check that the generated file actually exists
            File fromFile = pair.getFirst().getOutputFile();

            if (fromFile.isFile()) {
                // file already pre-dex, just copy the output.
                Files.copy(pair.getFirst().getOutputFile(), outFile);
                incrementHits();
            }
        }
    }

    @Override
    protected Node createItemNode(
            @NonNull Document document,
            @NonNull DexKey itemKey,
            @NonNull BaseItem item) throws IOException {
        Node itemNode = super.createItemNode(document, itemKey, item);

        Attr attr = document.createAttribute(ATTR_JUMBO_MODE);
        attr.setValue(Boolean.toString(itemKey.isJumboMode()));
        itemNode.getAttributes().setNamedItem(attr);

        return itemNode;
    }
}
