#!/usr/bin/env perl

# Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer. 
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution. 
# 3.  Neither the name of Apple Inc. ("Apple") nor the names of
#     its contributors may be used to endorse or promote products derived
#     from this software without specific prior written permission. 
#
# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Script to do file renaming.

use strict;
use warnings;
use File::Find;
use FindBin;
use lib $FindBin::Bin;
use webkitdirs;
use VCSUtils;

setConfiguration();
chdirWebKit();

my %words;

# find all files we want to process

my @paths;
find(\&wanted, "Source/JavaScriptCore");
find(\&wanted, "Source/WebCore");
find(\&wanted, "Source/WebKitLegacy");
find(\&wanted, "Source/WebKit");

sub wanted
{
    my $file = $_;

    if ($file eq "icu") {
        $File::Find::prune = 1;
        return;
    }

    if ($file =~ /^\../) {
        $File::Find::prune = 1;
        return;
    }

    return if $file =~ /^ChangeLog/;
    return if -d $file;

    push @paths, $File::Find::name;
}

my %renames = (
);

my %renamesContemplatedForTheFuture = (
);

# rename files

my %newFile;
for my $file (sort @paths) {
    my $f = $file;
    $f = "$1$renames{$2}" if $f =~ /^(.*\/)(\w+\.\w+)$/ && $renames{$2};
    $newFile{$file} = $f if $f ne $file;
}

for my $file (sort @paths) {
    if ($newFile{$file}) {
        my $newFile = $newFile{$file};
        print "Renaming $file to $newFile\n";
        scmMoveOrRenameFile($file, $newFile);
    }
}

# change all file contents

for my $file (sort @paths) {
    $file = $newFile{$file} if $newFile{$file};
    my $contents;
    {
        local $/;
        open FILE, $file or die;
        $contents = <FILE>;
        close FILE;
    }
    my $newContents = $contents;

    for my $from (keys %renames) {
        $newContents =~ s/\b\Q$from\E(?!\w)/$renames{$from}/g; # this " unconfuses Xcode syntax highlighting
    }

    if ($newContents ne $contents) {
        open FILE, ">", $file or die;
        print FILE $newContents;
        close FILE;
    }
}
