#! /usr/bin/env python3

#                   PCRE2 UNICODE PROPERTY SUPPORT
#                   ------------------------------
#
# This file auto-generates Unicode property tests and their expected output.
# It is recommended to re-run this generator after the Unicode files are
# updated. The names of the generated files are `testinput` and `testoutput`
# and should be copied over to replace either test26 or test27 files.

import re
import sys

from GenerateCommon import \
  script_names, \
  script_abbrevs

def write_both(text):
  input_file.write(text)
  output_file.write(text)

def to_string_char(ch_idx):
  if ch_idx < 128:
    if ch_idx < 16:
      return "\\x{0%x}" % ch_idx
    if ch_idx >= 32:
      return chr(ch_idx)
  return "\\x{%x}" % ch_idx

try:
  input_file = open("testinput", "w")
  output_file = open("testoutput", "w")
except IOError:
  print("** Couldn't create output files")
  sys.exit(1)

write_both("# These tests were generated by maint/GenerateTest.py using PCRE2's UCP\n");
write_both("# data, do not edit unless that data has changed and they are reflecting\n");
write_both("# a previous version.\n\n");

# ---------------------------------------------------------------------------
#                      UNICODE SCRIPT EXTENSION TESTS
# ---------------------------------------------------------------------------


def gen_script_tests():
  script_data = [None] * len(script_names)
  char_data = [None] * 0x110000

  property_re = re.compile(r"^([0-9A-F]{4,6})(?:\.\.([0-9A-F]{4,6}))? +; ([A-Za-z_ ]+[A-Za-z]) +#")
  prev_name = ""
  script_idx = -1

  with open("Unicode.tables/Scripts.txt") as f:
    version_pat = r"^# Scripts-(\d+\.\d+\.\d+)\.txt$"
    v = re.match(version_pat, f.readline())
    unicode_version = v.group(1)

    write_both("# Unicode Script Extension tests for version " + unicode_version + "\n\n")
    write_both("#perltest\n\n")

    for line in f:
      match_obj = property_re.match(line)

      if match_obj == None:
        continue

      name = match_obj.group(3)
      if name != prev_name:
        script_idx = script_names.index(name)
        prev_name = name

      low = int(match_obj.group(1), 16)
      high = low
      char_data[low] = name

      if match_obj.group(2) != None:
        high = int(match_obj.group(2), 16)
        for idx in range(low + 1, high + 1):
           char_data[idx] = name

      if script_data[script_idx] == None:
        script_data[script_idx] = [low, None, None, None, None]
      script_data[script_idx][1] = high

  extended_script_indicies = {}

  with open("Unicode.tables/ScriptExtensions.txt") as f:
    for line in f:
      match_obj = property_re.match(line)

      if match_obj == None:
        continue

      low = int(match_obj.group(1), 16)
      high = low
      if match_obj.group(2) != None:
        high = int(match_obj.group(2), 16)

      for abbrev in match_obj.group(3).split(" "):
        if abbrev not in extended_script_indicies:
          idx = script_abbrevs.index(abbrev)
          extended_script_indicies[abbrev] = idx
          rec = script_data[idx]
          rec[2] = low
          rec[3] = high
        else:
          idx = extended_script_indicies[abbrev]
          rec = script_data[idx]
          if rec[2] > low:
            rec[2] = low
          if rec[3] < high:
            rec[3] = high

        if rec[4] == None:
          name = script_names[idx]
          for idx in range(low, high + 1):
            if char_data[idx] != name:
              rec[4] = idx
              break

  long_property_name = False

  for idx, rec in enumerate(script_data):
    script_name = script_names[idx]

    if script_name == "Unknown":
      continue

    script_abbrev = script_abbrevs[idx]

    write_both("# Base script check\n")
    write_both("/^\\p{sc=%s}/utf\n" % script_name)
    write_both("    %s\n" % to_string_char(rec[0]))
    output_file.write(" 0: %s\n" % to_string_char(rec[0]))
    write_both("\n")

    write_both("/^\\p{Script=%s}/utf\n" % script_abbrev)
    write_both("    %s\n" % to_string_char(rec[1]))
    output_file.write(" 0: %s\n" % to_string_char(rec[1]))
    write_both("\n")

    if rec[2] != None:
      property_name = "scx"
      if long_property_name:
        property_name = "Script_Extensions"

      write_both("# Script extension check\n")
      write_both("/^\\p{%s}/utf\n" % script_name)
      write_both("    %s\n" % to_string_char(rec[2]))
      output_file.write(" 0: %s\n" % to_string_char(rec[2]))
      write_both("\n")

      write_both("/^\\p{%s=%s}/utf\n" % (property_name, script_abbrev))
      write_both("    %s\n" % to_string_char(rec[3]))
      output_file.write(" 0: %s\n" % to_string_char(rec[3]))
      write_both("\n")

      long_property_name = not long_property_name

      if rec[4] != None:
        write_both("# Script extension only character\n")
        write_both("/^\\p{%s}/utf\n" % script_name)
        write_both("    %s\n" % to_string_char(rec[4]))
        output_file.write(" 0: %s\n" % to_string_char(rec[4]))
        write_both("\n")

        write_both("/^\\p{sc=%s}/utf\n" % script_name)
        write_both("    %s\n" % to_string_char(rec[4]))
        output_file.write("No match\n")
        write_both("\n")
      else:
        print("External character has not found for %s" % script_name)

    high = rec[1]
    if rec[3] != None and rec[3] > rec[1]:
      high = rec[3]
    write_both("# Character not in script\n")
    write_both("/^\\p{%s}/utf\n" % script_name)
    write_both("    %s\n" % to_string_char(high + 1))
    output_file.write("No match\n")
    write_both("\n")

gen_script_tests()

write_both("# End of test\n")
