<?php
namespace libphonenumber\buildtools;

use libphonenumber\PhoneMetadata;

/**
 * Tool to convert phone number metadata from the XML format to protocol buffer format.
 *
 * @author Davide Mendolia
 * @internal
 */
class BuildMetadataPHPFromXml
{
    const GENERATION_COMMENT = <<<EOT
/**
 * This file has been @generated by a phing task by {@link BuildMetadataPHPFromXml}.
 * See [README.md](README.md#generating-data) for more information.
 *
 * Pull requests changing data in these files will not be accepted. See the
 * [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
 * metadata changes.
 *
 * Do not modify this file directly!
 */


EOT;
    const MAP_COMMENT = <<<EOT
  // A mapping from a country code to the region codes which denote the
  // country/region represented by that country code. In the case of multiple
  // countries sharing a calling code, such as the NANPA countries, the one
  // indicated with "isMainCountryForCode" in the metadata should be first.

EOT;
    const COUNTRY_CODE_SET_COMMENT =
        "  // A set of all country codes for which data is available.\n";
    const REGION_CODE_SET_COMMENT =
        "  // A set of all region codes for which data is available.\n";

    public function start($inputFile, $outputDir, $filePrefix, $mappingClass, $mappingClassLocation, $liteBuild)
    {
        $savePath = $outputDir . $filePrefix;

        $metadataCollection = BuildMetadataFromXml::buildPhoneMetadataCollection($inputFile, $liteBuild, false);
        $this->writeMetadataToFile($metadataCollection, $savePath);

        $countryCodeToRegionCodeMap = BuildMetadataFromXml::buildCountryCodeToRegionCodeMap($metadataCollection);
        // Sort $countryCodeToRegionCodeMap just to have the regions in order
        \ksort($countryCodeToRegionCodeMap);
        $this->writeCountryCallingCodeMappingToFile($countryCodeToRegionCodeMap, $mappingClassLocation, $mappingClass);
    }

    /**
     * @param $metadataCollection PhoneMetadata[]
     * @param $filePrefix
     */
    private function writeMetadataToFile($metadataCollection, $filePrefix)
    {
        foreach ($metadataCollection as $metadata) {
            /** @var $phoneMetadata PhoneMetadata */
            $regionCode = $metadata->getId();
            // For non-geographical country calling codes (e.g. +800), use the country calling codes
            // instead of the region code to form the file name.
            if ($regionCode === '001' || $regionCode == '') {
                $regionCode = $metadata->getCountryCode();
            }

            $data = '<?php' . PHP_EOL
                . self::GENERATION_COMMENT . PHP_EOL
                . 'return ' . \var_export($metadata->toArray(), true) . ';' . PHP_EOL;

            \file_put_contents($filePrefix . '_' . $regionCode . '.php', $data);
        }
    }

    private function writeCountryCallingCodeMappingToFile($countryCodeToRegionCodeMap, $outputDir, $mappingClass)
    {
        // Find out whether the countryCodeToRegionCodeMap has any region codes or country
        // calling codes listed in it.
        $hasRegionCodes = false;
        foreach ($countryCodeToRegionCodeMap as $key => $listWithRegionCode) {
            if (\count($listWithRegionCode) > 0) {
                $hasRegionCodes = true;
                break;
            }
        }

        $hasCountryCodes = (\count($countryCodeToRegionCodeMap) > 1);

        $variableName = \lcfirst($mappingClass);

        $data = '<?php' . PHP_EOL .
            self::GENERATION_COMMENT . PHP_EOL .
            'namespace libphonenumber;' . PHP_EOL .
            "class {$mappingClass} {" . PHP_EOL .
            PHP_EOL;

        if ($hasRegionCodes && $hasCountryCodes) {
            $data .= self::MAP_COMMENT . PHP_EOL;
            $data .= "   public static \${$variableName} = " . \var_export(
                $countryCodeToRegionCodeMap,
                true
            ) . ';' . PHP_EOL;
        } elseif ($hasCountryCodes) {
            $data .= self::COUNTRY_CODE_SET_COMMENT . PHP_EOL;
            $data .= "   public static \${$variableName} = " . \var_export(
                \array_keys($countryCodeToRegionCodeMap),
                true
            ) . ';' . PHP_EOL;
        } else {
            $data .= self::REGION_CODE_SET_COMMENT . PHP_EOL;
            $data .= "   public static \${$variableName} = " . \var_export(
                $countryCodeToRegionCodeMap[0],
                true
            ) . ';' . PHP_EOL;
        }

        $data .= PHP_EOL .
            '}' . PHP_EOL;

        \file_put_contents($outputDir . $mappingClass . '.php', $data);
    }
}
