/*
 * Copyright © 2012-2015 Cask Data, Inc.
 *
 * 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 co.cask.cdap.cli.command.app;

import co.cask.cdap.api.artifact.ArtifactScope;
import co.cask.cdap.cli.ArgumentName;
import co.cask.cdap.cli.CLIConfig;
import co.cask.cdap.cli.ElementType;
import co.cask.cdap.cli.english.Article;
import co.cask.cdap.cli.english.Fragment;
import co.cask.cdap.cli.util.AbstractAuthCommand;
import co.cask.cdap.cli.util.FilePathResolver;
import co.cask.cdap.client.ApplicationClient;
import co.cask.cdap.proto.Id;
import co.cask.cdap.proto.artifact.AppRequest;
import co.cask.cdap.proto.artifact.ArtifactSummary;
import co.cask.common.cli.Arguments;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.inject.Inject;

import java.io.File;
import java.io.FileReader;
import java.io.PrintStream;

/**
 * Deploys an application from an existing artifact.
 */
public class CreateAppCommand extends AbstractAuthCommand {
  private static final Gson GSON = new Gson();
  private final ApplicationClient applicationClient;
  private final FilePathResolver resolver;

  @Inject
  public CreateAppCommand(ApplicationClient applicationClient, FilePathResolver resolver, CLIConfig cliConfig) {
    super(cliConfig);
    this.applicationClient = applicationClient;
    this.resolver = resolver;
  }

  @Override
  public void perform(Arguments arguments, PrintStream output) throws Exception {
    String appName = arguments.get(ArgumentName.APP.toString());
    Id.Application appId = Id.Application.from(cliConfig.getCurrentNamespace(), appName);

    String artifactName = arguments.get(ArgumentName.ARTIFACT_NAME.toString());
    String artifactVersion = arguments.get(ArgumentName.ARTIFACT_VERSION.toString());
    ArtifactScope artifactScope = ArtifactScope.valueOf(arguments.get(ArgumentName.SCOPE.toString()).toUpperCase());
    ArtifactSummary artifact = new ArtifactSummary(artifactName, artifactVersion, artifactScope);

    JsonObject config = new JsonObject();
    String configPath = arguments.getOptional(ArgumentName.APP_CONFIG_FILE.toString());
    if (configPath != null) {
      File configFile = resolver.resolvePathToFile(configPath);
      try (FileReader reader = new FileReader(configFile)) {
        config = GSON.fromJson(reader, JsonObject.class);
      }
    }

    AppRequest<JsonObject> appRequest = new AppRequest<>(artifact, config);
    applicationClient.deploy(appId, appRequest);
    output.println("Successfully created application");
  }

  @Override
  public String getPattern() {
    return String.format("create app <%s> <%s> <%s> <%s> [<%s>]", ArgumentName.APP, ArgumentName.ARTIFACT_NAME,
                         ArgumentName.ARTIFACT_VERSION, ArgumentName.SCOPE, ArgumentName.APP_CONFIG_FILE);
  }

  @Override
  public String getDescription() {
    return String.format("Creates %s from an artifact with optional configuration.", Fragment.of(
      Article.A, ElementType.APP.getName()));
  }
}

@@ -2782,56 +2782,115 @@
     
-config = GSON.fromJson(reader, JsonObject.class)
+ConfigFile configContents = GSON.fromJson(reader, ConfigFile.class);%0A        config = configContents.config
 ;%0A  
@@ -3488,68 +3488,555 @@
 ion.
-%22, Fragment.of(%0A      Article.A, ElementType.APP.getName()))
+ If configuration is needed, it %22 +%0A      %22must be given as a file whose contents are a JSON Object containing the application config. %22 +%0A      %22For example, the file contents could contain: '%7B %5C%22config%5C%22: %7B %5C%22stream%5C%22: %5C%22purchases%5C%22 %7D %7D'. In this case, %22 +%0A      %22the application would recieve '%7B %5C%22stream%5C%22: %5C%22purchases%5C%22 %7D' as its config object.%22,%0A      Fragment.of(Article.A, ElementType.APP.getName()));%0A  %7D%0A%0A  // simple class for deserializing contents of config file.%0A  private static final class ConfigFile %7B%0A    private JsonObject config
 ;%0A  

fix create app command so that the config sent in the request comes from a config field in the file contents. This lets us extend the object if we have more arguments in the future, and it also makes it so that the same file can be used to create an app through curl and the CLI