//   Copyright 2012 Georg-August-Universität Göttingen, Germany
//
//   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 de.ugoe.cs.autoquest.plugin.html.commands;

import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;

import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement;
import de.ugoe.cs.autoquest.plugin.html.HTMLLogParser;
import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLServer;
import de.ugoe.cs.util.console.Command;
import de.ugoe.cs.util.console.Console;

/**
 * <p>
 * Command to restructure log files of the HTML monitor to be able to easily separate the logs
 * of different web sites.
 * </p>
 * 
 * @author Patrick Harms
 * @version 1.0
 */
public class CMDcorrectHTMLLogDirs implements Command {

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.util.console.Command#run(java.util.List)
     */
    @Override
    public void run(List<Object> parameters) {
        String path;

        try {
            path = (String) parameters.get(0);
        }
        catch (Exception e) {
            throw new IllegalArgumentException("illegal parameters provided: " + e);
        }

        File folder = new File(path);
        if (!folder.isDirectory()) {
            Console.printerrln(path + " is not a directory");
            return;
        }

        correctDirectory(folder, folder);

    }

    /**
     * <p>
     * method for recursively checking each file in a directory structure. Each file is parsed
     * and if a server could be determined in the file, the file is moved into a new directory
     * structure which starts with the server and its port followed by the user session id.
     * </p>
     *
     * @param file       the file to be handled. If it is a folder, the method calls itself for
     *                   each of the children of the folder
     * @param mainFolder the main folder into which the new directory structure is to be created
     *                   (usually the same directory from which the recursion began)
     */
    private void correctDirectory(File file, File mainFolder) {
        if (file.isDirectory()) {
            String[] children = file.list();
            Arrays.sort(children);
            
            for (String child : children) {
                File childFile = new File(file, child);
                correctDirectory(childFile, mainFolder);
            }
        }
        else if (file.isFile()) {
            String source = file.getAbsolutePath();
            Console.traceln(Level.INFO, "Processing file: " + source);
            String serverName = null;
            
            HTMLLogParser parser = new HTMLLogParser(new HashMap<String, List<String>>());
            try {
                parser.parseFile(file);
            }
            catch (Exception e) {
                // ignore as long as we were able to determine a server
            }
            
            for (IGUIElement server : parser.getGuiModel().getRootElements()) {
                if (server instanceof HTMLServer) {
                    serverName = ((HTMLServer) server).getHost() + "_" +
                        ((HTMLServer) server).getPort();
                }
            }
            
            if (serverName != null) {
                File destination = new File(mainFolder, serverName);
                destination = new File(destination, file.getParentFile().getName());
                
                if (!destination.exists()) {
                    if (!destination.mkdirs()) {
                        Console.printerrln("Could not create directory " + destination);
                        Console.printerrln("not moving " + file);
                    }
                }
                else if (!destination.isDirectory()) {
                    Console.printerrln
                        ("Destination " + destination + " already exists but is not a directory");
                    Console.printerrln("not moving " + file);
                }
                
                destination = new File(destination, file.getName());
                
                // we seem to need both comparisons, as the first one does not always work
                if (!file.equals(destination) &&
                    !file.getAbsolutePath().equals(destination.getAbsolutePath()))
                {
                    if (file.renameTo(destination)) {
                        Console.println("moved "  + file + " to " + destination);

                        if ((file.getParentFile().list() == null) ||
                            (file.getParentFile().list().length == 0))
                        {
                            if (file.getParentFile().delete()) {
                                Console.println("removed directory "  + file.getParentFile());
                            }
                            else {
                                Console.println
                                    ("could not remove directory "  + file.getParentFile());                            
                            }
                        }
                    }
                    else {
                        Console.println("could not move "  + file + " to " + destination);
                    }
                }
            }
            else {
                Console.printerrln("Could not determine a server name in " + source);
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.util.console.Command#help()
     */
    @Override
    public String help() {
        return "correctHTMLLogDirs <directory>";
    }

}
