/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <cctype>
#include <map>
#include <vector>

#include "src/compiler/config.h"
#include "src/compiler/ruby_generator.h"
#include "src/compiler/ruby_generator_helpers-inl.h"
#include "src/compiler/ruby_generator_map-inl.h"
#include "src/compiler/ruby_generator_string-inl.h"

using grpc::protobuf::FileDescriptor;
using grpc::protobuf::ServiceDescriptor;
using grpc::protobuf::MethodDescriptor;
using grpc::protobuf::io::Printer;
using grpc::protobuf::io::StringOutputStream;
using std::map;
using std::vector;

namespace grpc_ruby_generator {
namespace {

// Prints out the method using the ruby gRPC DSL.
void PrintMethod(const MethodDescriptor *method, const grpc::string &package,
                 Printer *out) {
  grpc::string input_type = RubyTypeOf(method->input_type()->full_name(), package);
  if (method->client_streaming()) {
    input_type = "stream(" + input_type + ")";
  }
  grpc::string output_type = RubyTypeOf(method->output_type()->full_name(), package);
  if (method->server_streaming()) {
    output_type = "stream(" + output_type + ")";
  }
  std::map<grpc::string, grpc::string> method_vars =
      ListToDict({"mth.name", method->name(), "input.type", input_type,
                  "output.type", output_type, });
  out->Print(method_vars, "rpc :$mth.name$, $input.type$, $output.type$\n");
}

// Prints out the service using the ruby gRPC DSL.
void PrintService(const ServiceDescriptor *service, const grpc::string &package,
                  Printer *out) {
  if (service->method_count() == 0) {
    return;
  }

  // Begin the service module
  std::map<grpc::string, grpc::string> module_vars =
      ListToDict({"module.name", CapitalizeFirst(service->name()), });
  out->Print(module_vars, "module $module.name$\n");
  out->Indent();

  // TODO(temiola): add documentation
  grpc::string doc = "TODO: add proto service documentation here";
  std::map<grpc::string, grpc::string> template_vars =
      ListToDict({"Documentation", doc, });
  out->Print("\n");
  out->Print(template_vars, "# $Documentation$\n");
  out->Print("class Service\n");

  // Write the indented class body.
  out->Indent();
  out->Print("\n");
  out->Print("include GRPC::GenericService\n");
  out->Print("\n");
  out->Print("self.marshal_class_method = :encode\n");
  out->Print("self.unmarshal_class_method = :decode\n");
  std::map<grpc::string, grpc::string> pkg_vars =
      ListToDict({"service_full_name", service->full_name()});
  out->Print(pkg_vars, "self.service_name = '$service_full_name$'\n");
  out->Print("\n");
  for (int i = 0; i < service->method_count(); ++i) {
    PrintMethod(service->method(i), package, out);
  }
  out->Outdent();

  out->Print("end\n");
  out->Print("\n");
  out->Print("Stub = Service.rpc_stub_class\n");

  // End the service module
  out->Outdent();
  out->Print("end\n");
}

}  // namespace

grpc::string GetServices(const FileDescriptor *file) {
  grpc::string output;
  {
    // Scope the output stream so it closes and finalizes output to the string.

    StringOutputStream output_stream(&output);
    Printer out(&output_stream, '$');

    // Don't write out any output if there no services, to avoid empty service
    // files being generated for proto files that don't declare any.
    if (file->service_count() == 0) {
      return output;
    }

    // Write out a file header.
    std::map<grpc::string, grpc::string> header_comment_vars = ListToDict(
        {"file.name", file->name(), "file.package", file->package(), });
    out.Print("# Generated by the protocol buffer compiler.  DO NOT EDIT!\n");
    out.Print(header_comment_vars,
              "# Source: $file.name$ for package '$file.package$'\n");

    out.Print("\n");
    out.Print("require 'grpc'\n");
    // Write out require statemment to import the separately generated file
    // that defines the messages used by the service. This is generated by the
    // main ruby plugin.
    std::map<grpc::string, grpc::string> dep_vars =
        ListToDict({"dep.name", MessagesRequireName(file), });
    out.Print(dep_vars, "require '$dep.name$'\n");

    // Write out services within the modules
    out.Print("\n");
    std::vector<grpc::string> modules = Split(file->package(), '.');
    for (size_t i = 0; i < modules.size(); ++i) {
      std::map<grpc::string, grpc::string> module_vars =
          ListToDict({"module.name", CapitalizeFirst(modules[i]), });
      out.Print(module_vars, "module $module.name$\n");
      out.Indent();
    }
    for (int i = 0; i < file->service_count(); ++i) {
      auto service = file->service(i);
      PrintService(service, file->package(), &out);
    }
    for (size_t i = 0; i < modules.size(); ++i) {
      out.Outdent();
      out.Print("end\n");
    }
  }
  return output;
}

}  // namespace grpc_ruby_generator
