/*
 * Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.release;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import software.amazon.awssdk.utils.Logger;
import software.amazon.awssdk.utils.Validate;

/**
 * A command line application to update an existing service.
 *
 * Example usage:
 * <pre>
  mvn exec:java -pl :release-scripts \
      -Dexec.mainClass="software.amazon.awssdk.release.UpdateServiceMain" \
      -Dexec.args="--maven-project-root /path/to/root
                   --service-module-name service-module-name
                   --service-json /path/to/service-2.json
                   [--paginators-json /path/to/paginators-1.json
                    --waiters-json /path/to/waiters-2.json]"
 * </pre>
 */
public class UpdateServiceMain extends Cli {
    private static final Logger log = Logger.loggerFor(UpdateServiceMain.class);

    private UpdateServiceMain() {
        super(requiredOption("service-module-name", "The name of the service module to be created."),
              requiredOption("maven-project-root", "The root directory for the maven project."),
              requiredOption("service-json", "The service-2.json file for the service."),
              optionalOption("paginators-json", "The paginators-1.json file for the service."),
              optionalOption("waiters-json", "The waiters-2.json file for the service."));
    }

    public static void main(String[] args) {
        new UpdateServiceMain().run(args);
    }

    @Override
    protected void run(CommandLine commandLine) throws Exception {
        new ServiceUpdater(commandLine).run();
    }

    private static class ServiceUpdater {
        private final String serviceModuleName;
        private final Path mavenProjectRoot;
        private final Path serviceJson;
        private final Path paginatorsJson;
        private final Path waitersJson;

        private ServiceUpdater(CommandLine commandLine) {
            this.mavenProjectRoot = Paths.get(commandLine.getOptionValue("maven-project-root").trim());
            this.serviceModuleName = commandLine.getOptionValue("service-module-name").trim();
            this.serviceJson = Paths.get(commandLine.getOptionValue("service-json").trim());
            this.paginatorsJson = optionalPath(commandLine.getOptionValue("paginators-json"));
            this.waitersJson = optionalPath(commandLine.getOptionValue("waiters-json"));
        }

        private Path optionalPath(String path) {
            path = StringUtils.trimToNull(path);
            if (path != null) {
                return Paths.get(path);
            }
            return null;
        }

        public void run() throws Exception {
            Validate.isTrue(Files.isRegularFile(serviceJson), serviceJson + " is not a file.");

            Path codegenFileLocation = codegenFileLocation(serviceModuleName);

            copyFile(serviceJson, codegenFileLocation.resolve("service-2.json"));
            copyFile(paginatorsJson, codegenFileLocation.resolve("paginators-1.json"));
            copyFile(waitersJson, codegenFileLocation.resolve("waiters-2.json"));
        }

        private Path codegenFileLocation(String serviceModuleName) {
            String actualServiceModuleName = actualServiceModuleName(serviceModuleName);

            Path codegenPath = mavenProjectRoot.resolve("services")
                                               .resolve(actualServiceModuleName)
                                               .resolve("src")
                                               .resolve("main")
                                               .resolve("resources")
                                               .resolve("codegen-resources");

            switch (actualServiceModuleName) {
                case "waf":
                case "dynamodb":
                    return codegenPath.resolve(serviceModuleName);
                default:
                    return codegenPath;
            }
        }

        private String actualServiceModuleName(String serviceModuleName) {
            switch (serviceModuleName) {
                case "wafregional":
                    return "waf";
                case "dynamodbstreams":
                    return "dynamodb";
                default:
                    return serviceModuleName;
            }
        }

        private void copyFile(Path source, Path destination) throws IOException {
            if (source != null && Files.isRegularFile(source)) {
                log.info(() -> "Copying " + source + " to " + destination);
                FileUtils.copyFile(source.toFile(), destination.toFile());
            }
        }
    }
}

@@ -1732,24 +1732,116 @@
 created.%22),%0A
+              requiredOption(%22service-id%22, %22The service ID of the service to be updated.%22),%0A
             
@@ -2521,32 +2521,72 @@
 viceModuleName;%0A
+        private final String serviceId;%0A
         private 
@@ -2892,32 +2892,110 @@
 root%22).trim());%0A
+            this.serviceId = commandLine.getOptionValue(%22service-id%22).trim();%0A
             this
@@ -3791,32 +3791,43 @@
 erviceModuleName
+, serviceId
 );%0A%0A            
@@ -4146,100 +4146,29 @@
 Name
-) %7B%0A            String actualServiceModuleName = actualServiceModuleName(serviceModuleName);
+, String serviceId) %7B
 %0A%0A  
@@ -4289,23 +4289,17 @@
 resolve(
-actualS
+s
 erviceMo
@@ -4607,365 +4607,17 @@
 ch (
-actualServiceModuleName) %7B%0A                case %22waf%22:%0A                case %22dynamodb%22:%0A                    return codegenPath.resolve(serviceModuleName);%0A                default:%0A                    return codegenPath;%0A            %7D%0A        %7D%0A%0A        private String actualServiceModuleName(String serviceModuleName) %7B%0A            switch (serviceModuleName
+serviceId
 ) %7B%0A
@@ -4656,42 +4656,8 @@
 l%22:%0A
-                    return %22waf%22;%0A
     
@@ -4723,18 +4723,38 @@
 urn 
-%22dynamodb%22
+codegenPath.resolve(serviceId)
 ;%0A  
@@ -4803,33 +4803,27 @@
  return 
-serviceModuleName
+codegenPath
 ;%0A      

Use module name as-is, service-id as sub dir