/*
 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.sjavac;

import java.io.*;
import java.net.URI;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;

import com.sun.tools.sjavac.options.Options;
import com.sun.tools.sjavac.server.JavacService;

/**
 * The copy file transform simply copies a matching file from -src to -d .
 * Such files are typically images, xml documents and other data files.
 *
 * <p><b>This is NOT part of any supported API.
 * If you write code that depends on this, you do so at your own
 * risk.  This code and its internal interfaces are subject to change
 * or deletion without notice.</b></p>
 */
public class CopyFile implements Transformer {

    public void setExtra(String e) {
    }

    public void setExtra(Options a) {
    }

    public boolean transform(JavacService javacService,
                             Map<String,Set<URI>> pkgSrcs,
                             Set<URI> visibleSrcs,
                             Map<URI,Set<String>> visibleClasses,
                             Map<String,Set<String>> oldPackageDependents,
                             URI destRoot,
                             Map<String,Set<URI>>    packageArtifacts,
                             Map<String,Set<String>> packageDependencies,
                             Map<String,String>      packagePubapis,
                             int debugLevel,
                             boolean incremental,
                             int numCores,
                             PrintStream out,
                             PrintStream err)
    {
        boolean rc = true;
        String dest_filename;
        File dest;

        for (String pkgName : pkgSrcs.keySet()) {
            String pkgNameF = Util.toFileSystemPath(pkgName);
            for (URI u : pkgSrcs.get(pkgName)) {
                File src = new File(u);
                File destDir;
                destDir = new File(destRoot.getPath()+File.separator+pkgNameF);
                dest_filename = destRoot.getPath()+File.separator+pkgNameF+File.separator+src.getName();
                dest = new File(dest_filename);

                if (!destDir.isDirectory()) {
                    if (!destDir.mkdirs()) {
                       Log.error("Error: The copier could not create the directory "+
                                           destDir.getPath());
                        return false;
                    }
                }

                Set<URI> as = packageArtifacts.get(pkgName);
                if (as == null) {
                    as = new HashSet<>();
                    packageArtifacts.put(pkgName, as);
                }
                as.add(dest.toURI());

                if (dest.exists() && dest.lastModified() > src.lastModified()) {
                    // A copied file exists, and its timestamp is newer than the source.
                    continue;
                }

                Log.info("Copying "+pkgNameF+File.separator+src.getName());

                try (InputStream fin = new FileInputStream(src);
                     OutputStream fout = new FileOutputStream(dest)) {
                    byte[] buf = new byte[1024];
                    int len;
                    while ((len = fin.read(buf)) > 0){
                        fout.write(buf, 0, len);
                    }
                }
                catch(IOException e){
                    Log.error("Could not copy the file "+src.getPath()+" to "+dest.getPath());
                    rc = false;
                }
            }
        }
        return rc;
    }
}
