/*
 * Copyright (C) 2008 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.
 */

import com.sun.javadoc.*;
import org.clearsilver.HDF;
import org.clearsilver.CS;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.util.ArrayList;

public class ClearPage
{
    /*
    public ClearPage()
    {
        String templ = "templates/index.cs";
        String filename = "docs/index.html";

        data.setValue("A.B.C", "1");
        data.setValue("A.B.D", "2");
    }
    */

    public static ArrayList<String> hdfFiles = new ArrayList<String>();

    private static ArrayList<String> mTemplateDirs = new ArrayList<String>();
    private static boolean mTemplateDirSet = false;

    public static String outputDir = "docs";
    public static String htmlDir = null;
    public static String toroot = null;

    public static void addTemplateDir(String dir)
    {
        mTemplateDirSet = true;
        mTemplateDirs.add(dir);

        File hdfFile = new File(dir, "data.hdf");
        if (hdfFile.canRead()) {
            hdfFiles.add(hdfFile.getPath());
        }
    }

    private static int countSlashes(String s)
    {
        final int N = s.length();
        int slashcount = 0;
        for (int i=0; i<N; i++) {
            if (s.charAt(i) == '/') {
                slashcount++;
            }
        }
        return slashcount;
    }

    public static void write(HDF data, String templ, String filename)
    {
        write(data, templ, filename, false);
    }

    public static void write(HDF data, String templ, String filename, boolean fullPath)
    {
        if (htmlDir != null) {
            data.setValue("hasindex", "true");
        }

        String toroot;
        if (ClearPage.toroot != null) {
            toroot = ClearPage.toroot;
        } else {
            int slashcount = countSlashes(filename);
            if (slashcount > 0) {
                toroot = "";
                for (int i=0; i<slashcount; i++) {
                    toroot += "../";
                }
            } else {
                toroot = "./";
            }
        }
        data.setValue("toroot", toroot);

        data.setValue("filename", filename);

        if (!fullPath) {
            filename = outputDir + "/" + filename;
        }

        int i=0;
        if (htmlDir != null) {
            data.setValue("hdf.loadpaths." + i, htmlDir);
            i++;
        }
        if (mTemplateDirSet) {
            for (String dir: mTemplateDirs) {
                data.setValue("hdf.loadpaths." + i, dir);
                i++;
            }
        } else {
            data.setValue("hdf.loadpaths." + i, "templates");
        }
        
        CS cs = new CS(data);
        cs.parseFile(templ);

        File file = new File(outputFilename(filename));
        
        ensureDirectory(file);

        OutputStreamWriter stream = null;
        try {
            stream = new OutputStreamWriter(
                            new FileOutputStream(file), "UTF-8");
            String rendered = cs.render();
            stream.write(rendered, 0, rendered.length());
        }
        catch (IOException e) {
            System.out.println("error: " + e.getMessage() + "; when writing file: " + filename);
        }
        finally {
            if (stream != null) {
                try {
                    stream.close();
                }
                catch (IOException e) {
                }
            }
        }
    }

    // recursively create the directories to the output
    public static void ensureDirectory(File f)
    {
        File parent = f.getParentFile();
        if (parent != null) {
            parent.mkdirs();
        }
    }

    public static void copyFile(File from, String toPath)
    {
        File to = new File(outputDir + "/" + toPath);
        FileInputStream in;
        FileOutputStream out;
        try {
            if (!from.exists()) {
                throw new IOException();
            }
            in = new FileInputStream(from);
        }
        catch (IOException e) {
            System.err.println(from.getAbsolutePath() + ": Error opening file");
            return ;
        }
        ensureDirectory(to);
        try {
            out = new FileOutputStream(to);
        }
        catch (IOException e) {
            System.err.println(from.getAbsolutePath() + ": Error opening file");
            return ;
        }

        long sizel = from.length();
        final int maxsize = 64*1024;
        int size = sizel > maxsize ? maxsize : (int)sizel;
        byte[] buf = new byte[size];
        while (true) {
            try {
                size = in.read(buf);
            }
            catch (IOException e) {
                System.err.println(from.getAbsolutePath()
                        + ": error reading file");
                break;
            }
            if (size > 0) {
                try {
                    out.write(buf, 0, size);
                }
                catch (IOException e) {
                    System.err.println(from.getAbsolutePath()
                        + ": error writing file");
                }
            } else {
                break;
            }
        }
        try {
            in.close();
        }
        catch (IOException e) {
        }
        try {
            out.close();
        }
        catch (IOException e) {
        }
    }
    
    /** Takes a string that ends w/ .html and changes the .html to htmlExtension */
    public static String outputFilename(String htmlFile) {
        if (!DroidDoc.htmlExtension.equals(".html") && htmlFile.endsWith(".html")) {
            return htmlFile.substring(0, htmlFile.length()-5) + DroidDoc.htmlExtension;
        } else {
            return htmlFile;
        }
    }

}