#
# Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#

#
#
#
# Perl script to generate ZoneData from Olson public time zone data.
#
# For J2SE before JDK1.3, see ../../README how to update TimeZone.java 
# static TimeZoneData.
# For J2SE since JDK1.4, this script is used to generate testdata(reference)
# for ZoneData.sh which is one of TimeZone Regression test.

$continue = 0;

# verbose flag
$verbose = 0;

# version of Olson's public zone information (e.g. "tzdata2000g")
$versionName = "unknown";

# Number of testdata files.
$count = 5;

# Display name datafile
$displayNameFile = "displaynames.txt";

# time zone IDs to be generated. If it's empty, then generate all time
# zone in the tzdata files.
@javatzids = ();

#
# Parses command-line options
#
while ($#ARGV >= 0) {
    if ($ARGV[0] =~ /^-v/) {
	$verbose = 1;
    } elsif ($ARGV[0] =~ /^-V/) {
	$versionName = $ARGV[1];
	shift(@ARGV);
    } else {
	@javatzids = &readIDs($ARGV[0]);
	last;
    }
    shift(@ARGV);
}

# Beginning year of testdata
($sec, $min, $hour, $mday, $mon, $year, $wday, $ydat, $isdst) = gmtime();
$baseYear = $year+1900;

if ($verbose == 1) {
    print STDERR "baseYear : $baseYear\n";
    print STDERR "versionName : $versionName\n";
}

# Open display name datafile
open (DNFD, ">$displayNameFile") || die ("$displayNameFile : open error.\n");

while(<STDIN>) {
    chop;
    if (/^\#/) { # skip comment line
	next;
    }
    @item = ("foo");

    # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    if ($continue == 1) {
	s/\#.*//; # chop trailing comments
	s/\s+$//;
	s/^\s+//;
	@item = split(/\s+/, $_);
	@item = ($zname, @item); # push zone name
    } elsif (/^Zone/) {
	s/\#.*//; # chop trailing comments
	s/\s+$//;
	@item = split(/\s+/, $_);
	$zname = $item[1];
	if (defined ($zones{$name})) {
	    printf STDERR "WARNING: duplicate definition of zone $name\n";
	}
	shift(@item);
    }
    if (@item[0] ne "foo") {
	if($#item == 3) { # find out no UNTIL line
	    $item[3] =~ s/%/%%/;
	    $zones{$item[0]} = "Zone $item[0]\t$item[1]\t$item[2]\t$item[3]";
	} else {
	    $continue = 1;
	    next;
	}
    }

    # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    if (/^Rule/) {
	($rule, $name, $from, $to, $type, $in, $on, $at, $save, $letter)
	  = split(/\s+/, $_);

	# matches specified year?
	for ($i = 0; $i < $count; $i++) {
	    if ($from <= $baseYear+$i && ($to >= $baseYear+$i || $to eq "max")
		|| ($from == $baseYear+$i && $to eq "only")) {
		if ($save ne "0") {
		    $rules[$i]{$name . "0"} = $_;
		} else {
		    $rules[$i]{$name . "1"} = $_;
		}
	    } else {
                if ($from <= $baseYear) {
                    if ($save ne "0") {
		        $oldRules[0]{$name} = $_;
		    } else {
		        $oldRules[1]{$name} = $_;
		    }
                }
	    }
	}
    }
    $continue = 0;
}

#
# Prepare output files
#
for ($i = 0, $fd = 0; $i < $count; $i++, $fd++) {
    $filename = "year".($baseYear+$i);
    open ($fd, ">$filename") || die ("$filename : open error.\n");
    print $fd "# Based on $versionName\n";
}

#
# If no IDs are specified, produce test data for all zones.
#
if ($#javatzids < 0) {
    @javatzids = keys(%zones);
}

foreach $z (@javatzids) {
    #
    # skip any Riyadh zones; ZoneData.java can't handle Riyada zones
    #
    next if ($z =~ /Riyadh/);

    for ($i = 0, $fd = 0; $i < $count; $i++, $fd++) {
	if (!defined($zones{$z})) {
	    printf $fd "$z ?\n";
	    printf STDERR "WARNING: java zone $z not found\n";
	    next;
	}
	@item = split(/\s+/, $zones{$z});
	if ($item[3] ne "-") {
	    printf $fd "$item[1] $item[2] ";
	    if (defined($rules[$i]{$item[3] . "0"})
		&& defined($rules[$i]{$item[3] . "1"})) {
		$rule0 = $rules[$i]{$item[3] . "0"};
		$rule1 = $rules[$i]{$item[3] . "1"};
		@r0 = split(/\s+/, $rule0);
		@r1 = split(/\s+/, $rule1);
		printf $fd "$r0[5] $r0[6] $r0[7] $r1[5] $r1[6] $r1[7] $r0[8]\n";
		printf $fd "$zones{$z}\n";
		printf $fd "$rule0\n";
		printf $fd "$rule1\n";
                if ($i == 0) {
                    $std = $dst = $item[4];
                    $std =~ s/%%s/$r1[9]/;
                    if ($r1[9] eq "-") {
                        $std =~ s/-//;
                    }
                    $dst =~ s/%%s/$r0[9]/;
                    if ($r0[9] eq "-") {
                        $dst =~ s/-//;
                    }
                    if ("$std$dst" =~ /[A-Z]/) {
                        print DNFD "$item[1] $std $dst\n";
                    }
                }
	    } else {
		printf $fd "-\n"; # In case we cannot find Rule, assume no DST.
		printf $fd "$zones{$z}\n";
		printf STDERR "WARNING: $z no rules defined for $item[3]\n";
                if ($i == 0) {
                    # About 30 time zones (e.g. Asia/Tokyo needs the following
                    # recovery.
                    if ($item[4] =~ m/%/) {
                        @r0 = split(/\s+/, $oldRules[0]{$item[3]});
                        @r1 = split(/\s+/, $oldRules[1]{$item[3]});
                        if ($i == 0) {
                            $std = $dst = $item[4];
                            $std =~ s/%%s/$r1[9]/;
                            if ($r1[9] eq "-") {
                                $std =~ s/-//;
                            }
                            $dst =~ s/%%s/$r0[9]/;
                            if ($r0[9] eq "-") {
                                $dst =~ s/-//;
                            }
                            if ("$std$dst" =~ /[A-Z]/) {
                                print DNFD "$item[1] $std $dst\n";
                            }
                        }
                    } else {
                        if ("$item[4]" =~ /[A-Z]/) {
                            print DNFD "$item[1] $item[4]\n";
                        }
                    }
                }
	    }
	} else {
	    printf $fd "$item[1] $item[2] $item[3]\n";
	    printf $fd "$zones{$z}\n";
            if ($i == 0 && "$item[4]" =~ /[A-Z]/) {
                print DNFD "$item[1] $item[4]\n";
            }
	}
    }
}

#
# Close all the output files
#
close (DNFD);
for ($i = 0, $fd = 0; $i < $count; $i++, $fd++) {
    close ($fd);
}

#
# Sort the displaynames.txt file
#
open my $fh, '<', $displayNameFile || die ("Can't open $displayNameFile for sorting\n");;
chomp(my @names = <$fh>);
close $fh;
open my $fh, '>', $displayNameFile;
foreach $line (sort @names) { print $fh $line,"\n"; }
close $fh;

exit(0);

sub readIDs {
    local ($file) = @_;
    local (@ids, $i);

    open(F, $file) || die "Fatal: can't open $file.\n";

    $i = 0;
    while (<F>) {
	chop;
	if (/^\#/) { # skip comment line
	    next;
	}

	# trim any leading and trailing space
	s/^\s+//;
	s/\s+$//;

        if (/^\s*$/) { # skip blank line
	    next;
	}

	$ids[$i++] = $_;
    }
    close(F);
    return @ids;
}