// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.api.doc;

import java.io.BufferedWriter;
import java.io.EOFException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class ApiXmlDocReader {
    public static void main(String[] args) {
        String newFile = null;
        String oldFile = null;
        String dirName = "";

        LinkedHashMap<String, Command> commands = new LinkedHashMap<String, Command>();
        LinkedHashMap<String, Command> oldCommands = new LinkedHashMap<String, Command>();
        ArrayList<Command> addedCommands = new ArrayList<Command>();
        ArrayList<Command> removedCommands = new ArrayList<Command>();
        HashMap<String, Command> stableCommands = new HashMap<String, Command>();

        XStream xs = new XStream(new DomDriver());
        xs.alias("command", Command.class);
        xs.alias("arg", Argument.class);

        List<String> argsList = Arrays.asList(args);
        Iterator<String> iter = argsList.iterator();
        while (iter.hasNext()) {
            String arg = iter.next();
            // populate the file names
            if (arg.equals("-new")) {
                newFile = iter.next();
            }
            if (arg.equals("-old")) {
                oldFile = iter.next();
            }
            if (arg.equals("-d")) {
                dirName = iter.next();
            }
        }

        try {
            try {
                ObjectInputStream inOld = xs.createObjectInputStream(new FileReader(oldFile));
                while (true) {
                    Command c1 = (Command) inOld.readObject();
                    oldCommands.put(c1.getName(), c1);
                }
            } catch (EOFException ex) {
                // EOF exception shows that there is no more objects in ObjectInputStream, so do nothing here
            }

            try {
                ObjectInputStream inNew = xs.createObjectInputStream(new FileReader(newFile));
                while (true) {
                    Command c = (Command) inNew.readObject();
                    commands.put(c.getName(), c);
                }
            } catch (EOFException ex) {
                // EOF exception shows that there is no more objects in ObjectInputStream, so do nothing here
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        // Check if any commands got added in new version
        for (String key : commands.keySet()) {
            if (!oldCommands.containsKey(key)) {
                addedCommands.add(commands.get(key));
            } else {
                stableCommands.put(commands.get(key).getName(), commands.get(key));
            }
        }

        // Check if any commands were removed in new version
        for (String key : oldCommands.keySet()) {
            if (!commands.containsKey(key)) {
                removedCommands.add(oldCommands.get(key));
                if (stableCommands.get(key) != null) {
                    stableCommands.remove(key);
                }
            }
        }

        try {
            FileWriter fstream = new FileWriter(dirName + "/diff.txt");
            BufferedWriter out = new BufferedWriter(fstream);

            // Print added commands
            out.write("Added commands:\n");
            for (Command c : addedCommands) {
                if (c.getDescription() != null && !c.getDescription().isEmpty()) {
                    out.write("\n    " + c.getName() + " (" + c.getDescription() + ")\n");
                } else {
                    out.write("\n    " + c.getName() + "\n");
                }

            }

            // Print removed commands
            out.write("\nRemoved commands:\n");
            for (Command c : removedCommands) {
                if (c.getDescription() != null && !c.getDescription().isEmpty()) {
                    out.write("\n\t" + c.getName() + " (" + c.getDescription() + ")\n");
                } else {
                    out.write("\n\t" + c.getName() + "\n");
                }

            }

            out.write("\nChanges in command type (sync versus async)\n");
            // Verify if the command was sync and became async and vice versa
            for (String key : stableCommands.keySet()) {
                if (commands.get(key).isAsync() != oldCommands.get(key).isAsync()) {
                    String type = "Sync";
                    if (commands.get(key).isAsync()) {
                        type = "Async";
                    }
                    out.write("\n\t" + stableCommands.get(key).getName() + " became " + type);
                }
            }

            // Print differences between commands arguments
            out.write("\n\nChanges in commands arguments:\n");
            for (String key : stableCommands.keySet()) {
                ArrayList<Argument> newReqArgs = new ArrayList<Argument>();
                ArrayList<Argument> removedReqArgs = new ArrayList<Argument>();
                HashMap<String, Argument> stableReqArgs = new HashMap<String, Argument>();
                ArrayList<Argument> newRespArgs = new ArrayList<Argument>();
                ArrayList<Argument> removedRespArgs = new ArrayList<Argument>();

                Command newCommand = commands.get(key);
                Command oldCommand = oldCommands.get(key);

                // Check if any request arguments were added in new version
                for (Argument arg : newCommand.getRequest()) {
                    if (oldCommand.getReqArgByName(arg.getName()) == null) {
                        if (!(arg.getName().equals("page") || arg.getName().equals("pagesize") || arg.getName().equals("keyword"))) {
                            newReqArgs.add(arg);
                        }
                    } else {
                        stableReqArgs.put(arg.getName(), arg);
                    }
                }

                // Check if any request arguments were removed in new version
                for (Argument arg : oldCommand.getRequest()) {
                    if (newCommand.getReqArgByName(arg.getName()) == null) {
                        removedReqArgs.add(arg);
                        if (stableReqArgs.get(arg.getName()) != null) {
                            stableReqArgs.remove(arg.getName());
                        }
                    }
                }

                // Compare stable request arguments of old and new version
                for (Iterator<String> i = stableReqArgs.keySet().iterator(); i.hasNext();) {
                    String argName = i.next();
                    if (oldCommand.getReqArgByName(argName).isRequired() == newCommand.getReqArgByName(argName).isRequired()) {
                        i.remove();
                    }
                }

                // Check if any response arguments were added in new version
                if (newCommand.getResponse() != null && oldCommand.getResponse() != null) {
                    for (Argument arg : newCommand.getResponse()) {
                        if (oldCommand.getResArgByName(arg.getName()) == null) {
                            newRespArgs.add(arg);
                        }
                    }

                    // Check if any response arguments were removed in new version
                    for (Argument arg : oldCommand.getResponse()) {
                        if (newCommand.getResArgByName(arg.getName()) == null) {
                            removedRespArgs.add(arg);
                        }
                    }
                }

                if (newReqArgs.size() != 0 || newRespArgs.size() != 0 || removedReqArgs.size() != 0 || removedRespArgs.size() != 0 || stableReqArgs.size() != 0 || stableReqArgs.size() != 0) {
                    StringBuffer commandInfo = new StringBuffer();
                    commandInfo.append("\n\t" + key);
                    out.write(commandInfo.toString());
                    out.write("\n");

                    // Request
                    if (newReqArgs.size() != 0 || removedReqArgs.size() != 0 || stableReqArgs.size() != 0) {
                        StringBuffer request = new StringBuffer();
                        request.append("\n\t\tRequest:\n");
                        out.write(request.toString());
                        if (newReqArgs.size() != 0) {
                            StringBuffer newParameters = new StringBuffer();
                            newParameters.append("\n\t\t\tNew parameters: ");
                            for (Argument newArg : newReqArgs) {
                                String isRequiredParam = "optional";
                                if (newArg.isRequired()) {
                                    isRequiredParam = "required";
                                }
                                newParameters.append(newArg.getName() + " (" + isRequiredParam + "), ");
                            }
                            newParameters.delete(newParameters.length() - 2, newParameters.length() - 1);
                            out.write(newParameters.toString());
                            out.write("\n");
                        }
                        if (removedReqArgs.size() != 0) {
                            StringBuffer removedParameters = new StringBuffer();
                            removedParameters.append("\n\t\t\tRemoved parameters: ");
                            for (Argument removedArg : removedReqArgs) {
                                removedParameters.append(removedArg.getName() + ", ");
                            }
                            removedParameters.delete(removedParameters.length() - 2, removedParameters.length() - 1);
                            out.write(removedParameters.toString());
                            out.write("\n");
                        }

                        if (stableReqArgs.size() != 0) {
                            StringBuffer changedParameters = new StringBuffer();
                            changedParameters.append("\n\t\t\tChanged parameters: ");
                            for (Argument stableArg : stableReqArgs.values()) {
                                String newRequired = "optional";
                                String oldRequired = "optional";
                                if (oldCommand.getReqArgByName(stableArg.getName()).isRequired() == true)
                                    oldRequired = "required";
                                if (newCommand.getReqArgByName(stableArg.getName()).isRequired() == true)
                                    newRequired = "required";
                                changedParameters.append(stableArg.getName() + " (old version - " + oldRequired + ", new version - " + newRequired + "), ");
                            }
                            changedParameters.delete(changedParameters.length() - 2, changedParameters.length() - 1);
                            out.write(changedParameters.toString());
                            out.write("\n");
                        }
                    }

                    // Response
                    if (newRespArgs.size() != 0 || removedRespArgs.size() != 0) {
                        StringBuffer changedResponseParams = new StringBuffer();
                        changedResponseParams.append("\n\t\tResponse:\n");
                        out.write(changedResponseParams.toString());
                        if (newRespArgs.size() != 0) {
                            StringBuffer newRespParams = new StringBuffer();
                            newRespParams.append("\n\t\t\tNew parameters: ");
                            for (Argument newArg : newRespArgs) {
                                newRespParams.append(newArg.getName() + ", ");
                            }
                            newRespParams.delete(newRespParams.length() - 2, newRespParams.length() - 1);
                            out.write(newRespParams.toString());
                            out.write("\n");
                        }
                        if (removedRespArgs.size() != 0) {
                            StringBuffer removedRespParams = new StringBuffer();
                            removedRespParams.append("\n\t\t\tRemoved parameters: ");
                            for (Argument removedArg : removedRespArgs) {
                                removedRespParams.append(removedArg.getName() + ", ");
                            }
                            removedRespParams.delete(removedRespParams.length() - 2, removedRespParams.length() - 1);
                            out.write(removedRespParams.toString());
                            out.write("\n");
                        }
                    }
                }
            }

            out.close();

        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
