package phpclient

import (
	"fmt"
	"io"

	"github.com/apex/rpc/internal/format"
	"github.com/apex/rpc/schema"
)

var call = `
  private function call($method, $body) {
    $header = "Content-type: application/json\r\n";

    if (isset($this->authToken)) {
      $header .= "Authorization: Bearer $this->authToken\r\n";
    }

    $options = array(
      'http' => array(
        'header'  => $header,
        'method'  => 'POST',
        'content' => json_encode($body)
      )
    );

    $url = $this->url . "/" . $method;
    $context = stream_context_create($options);
    $result = file_get_contents($url, false, $context);

    // TODO: how to check the status code and parse error from the body?

    return json_decode($result);
  }`

var class = `
class %s {
  protected $url;
  protected $authToken;

  /**
   * Create a new API client.
   *
   * @param string $url The endpoint URL.
   * @param string $authToken The authentication token [optional].
   */

  public function __construct($url, $authToken = null) {
    $this->url = $url;
    $this->authToken = $authToken;
  }
`

// Generate writes the PHP client implementations to w.
func Generate(w io.Writer, s *schema.Schema, className string) error {
	out := fmt.Fprintf

	out(w, "<?php\n")
	out(w, "// Do not edit, this file was generated by github.com/apex/rpc.\n")

	out(w, class, className)

	for _, m := range s.Methods {
		name := format.JsName(m.Name)

		// comment
		out(w, "\n")
		out(w, "  /**\n")
		out(w, "   * %s %s\n", name, m.Description)
		out(w, "   *\n")
		if len(m.Inputs) > 0 {
			out(w, "   * @param array $params The input parameters.\n")
		}
		if len(m.Outputs) > 0 {
			out(w, "   * @return array\n")
		}
		out(w, "   */\n")

		// method
		out(w, "  public function %s(", name)

		// input arg
		if len(m.Inputs) > 0 {
			out(w, "array $params")
		}
		out(w, ") {\n")

		// return
		if len(m.Inputs) > 0 {
			out(w, "    return $this->call(%q, $params);\n", m.Name)
		} else {
			out(w, "    return $this->call(%q, null);\n", m.Name)
		}

		// close
		out(w, "  }\n")
	}

	out(w, "%s\n", call)
	out(w, "}\n")

	return nil
}
