<?php
/*
 * This file is part of the protoc-gen-php package.
 *
 * (c) Shuhei Tanuma <shuhei.tanuma@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace protocolbuffers\generator\php;

use google\protobuf\EnumValueDescriptorProto;
use protocolbuffers\GeneratorContext;
use protocolbuffers\io\Printer;
use protocolbuffers\PragmaticInserter;
use protocolbuffers\SourceInfoDictionary;
use protocolbuffers\generator\php\Helper;

class EnumGenerator extends MessageGenerator
{
    /** @var \google\protobuf\EnumDescriptorProto  */
    protected $descriptor;

    public function __construct(GeneratorContext $context,
                                \google\protobuf\EnumDescriptorProto $descriptor,
                                &$file_list)
    {
        $this->descriptor = $descriptor;
        $this->context = $context;
        $this->file_list = &$file_list;

        if ($descriptor->file()->getOptions()->getExtension("php")->getMultipleFiles()) {
            $this->enclose_namespace_ = false;
        } else {
            $this->enclose_namespace_ = true;
        }
    }

    public function getEnumValueAsString(EnumValueDescriptorProto $value)
    {
        return $value->getName();
    }

    public function generate(Printer $printer)
    {
        if ($this->descriptor->file()->getOptions()->getExtension("php")->getMultipleFiles()) {
            $printer->put("<?php\n");
        }

        $this->printUseNameSpaceIfNeeded($printer);
        $printer->put(
            "/**\n" .
            " * Generated by the protocol buffer compiler.  DO NOT EDIT!\n" .
            " * source: `filename`\n" .
            " *\n",
            "filename",
            $this->descriptor->file()->getName()
        );
        $printer->put(" */\n");
        $printer->put("class `name` extends `base`\n{\n",
            "name",
            Helper::getClassName($this->descriptor),
            "base",
            Helper::getEnumClassName($this->descriptor)
        );
        $printer->indent();
        $printer->put("// @@protoc_insertion_point(traits:`name`)\n",
            "name", $this->descriptor->full_name);
        $printer->put("\n");

        foreach ($this->descriptor->getValue() as $value) {
            if ($dict = SourceInfoDictionary::get($this->descriptor->file()->getName(),
                    $this->descriptor->getName(),
                    $value->getName())
            ) {
                if ($dict->getLeadingComments()) {
                    $printer->put("/**\n");
                    $lines = preg_split("/\r?\n/", trim($dict->getLeadingComments()));

                    foreach ($lines as $line) {
                        $line = Helper::cleanupComment($line);
                        $printer->put(" * `comment`\n", "comment", $line);
                    }
                    $printer->put(" */\n");
                }
            }

            $printer->put(
                "const `name` = `number`;\n",
                "name", $this->getEnumValueAsString($value),
                "number", $value->getNumber()
            );
        }

        $printer->put("\n");
        $printer->put("// @@protoc_insertion_point(const_scope:`name`)\n",
            "name", $this->descriptor->full_name);

        $printer->put("\n");

        $printer->put("// @@protoc_insertion_point(class_scope:`name`)\n",
            "name", $this->descriptor->full_name);

        $printer->put("\n");

        $printer->put("/**\n");
        $printer->put(" * @return \\ProtocolBuffers\\EnumDescriptor\n");
        $printer->put(" */\n");
        $printer->put("public static function getEnumDescriptor()\n");
        $printer->put("{\n");
        $printer->indent();
        $printer->put("static \$descriptor;\n");
        $printer->put("if (!\$descriptor) {\n");
        $printer->indent();
        $printer->put("\$builder = new `builder`();\n",
            "builder",
            Helper::getEnumDescriptorBuilderClassName($this->descriptor)
        );
        foreach ($this->descriptor->getValue() as $value) {
            $printer->put("\$builder->addValue(new \\ProtocolBuffers\\EnumValueDescriptor(array(\n");
            $printer->indent();

            $printer->put("\"value\" => `value`,\n",
                "value", "self::" . $value->getName());
            $printer->put("\"name\"  => '`name`',\n",
                "name", $value->getName());
            $printer->outdent();
            $printer->put(")));\n");
        }

        $printer->put("// @@protoc_insertion_point(builder_scope:`name`)\n",
            "name", $this->descriptor->full_name);
        $printer->put("\$descriptor = \$builder->build();\n");

        $printer->outdent();
        $printer->put("}\n");
        $printer->put("return \$descriptor;\n");
        $printer->outdent();
        $printer->put("}\n");

        $printer->outdent();
        $printer->put("}\n");

        if ($this->enclose_namespace_) {
            $printer->outdent();
            $printer->put("}\n\n");
        }

        PragmaticInserter::execute($this->descriptor, $this->context);
    }
}
