=head1 NAME

CFX5::CCLDiff - Difference the CCL in two DEF files.

=head1 SYNOPSIS

  use CFX5::CCLDiff;

=head1 DESCRIPTION

Compares the CCL datasets from two named DEF files, and returns
a list of differences using full CCL format with :

  <Parameter Name>= <File 1 Value> -> <File 2 Value>

to highlight the differences.

=cut

package CFX5::CCLDiff;

use strict;

use CFX5::Output qw(:all);
use CFX5::CCLI;

=head2 DATA COMPARISON

=head3 compareDefs

   @diffs = compareDefs(File1,File2);

Returns the list of differents between the two files.

=cut

sub compareDefs {
  my ($self, $defOne, $defTwo) = @_;

#Get the CCL out of the DEF files

  my $ccldsOne = CFX5::CCLI::getcclds($defOne);
  my @cclOne;
  if (ref $ccldsOne) {
    @cclOne = $ccldsOne->data();
  } else {
    _error("Error getting CCL Data from $defOne.");
    return();
  };

  my $ccldsTwo = CFX5::CCLI::getcclds($defTwo);
  my @cclTwo;
  if (ref $ccldsTwo) {
    @cclTwo = $ccldsTwo->data();
  } else {
    _error("Error getting CCL Data from $defTwo.");
    return();
  };

  return $self->compareCCL(\@cclOne, \@cclTwo);
}

=head3 compareCCL

   @diffs = compareCCL(\@orig,\@new);

Returns the list of differents between the two files.

=cut

sub compareCCL {
  my $self=shift;
  my @cclOne=@{ (shift) };
  my @cclTwo=@{ (shift) };

# Diff the two data sets.  Note this must be done is two passes (one vs. two,
# then two vs. one).  This is because the CCL database is additive, and change
# lists don't report entries not defined in the second dataset.  This is contrary
# to formal 'diff' expectation, so we do two passes.

# The results from each pass are stored in a hash table pointing to pairs,
# where the key to the hash is the param path, and the value is a pair of
# [first file value, second file value].

  _debug("Comparing CCL");

  my $errors;
  my @tempDiffs;
  my %diffs;

  my $api = CFX5::CCLI::new_api_object();

  # Diff first to second
  $errors = $api->diffCCLData(\@cclTwo,\@cclOne,\@tempDiffs);

  # Check for errors
  if (defined($errors)) {
    _error("$errors\n");
    return();
  }

  # Store the first diffs in the hash table
  foreach my $diff (@tempDiffs) {
    my ($key,$first,$second) = split(/==/,$diff);
    $diffs{$key} = [$first,$second];
  }

  $#tempDiffs = -1;

  # Diff second to first
  $errors = $api->diffCCLData(\@cclOne,\@cclTwo,\@tempDiffs);

   # Check for errors
  if (defined($errors)) {
    _error("$errors\n");
    return();
  }

  # Store the second diffs in the hash table
  foreach my $diff (@tempDiffs) {
    my ($key,$second,$first) = split(/==/,$diff);
    $diffs{$key} = [$first,$second];
  }

#  #Create the diff output
   my @output;

   #Build up the lists differences in path format;
   my @diffPathList;

   foreach my $key (keys(%diffs)) {
     push @diffPathList, $key . "=" . $diffs{$key}[0] . " -> " . $diffs{$key}[1];
   }

   # Get a clean copy of the API to generate the differences in CCL format
   undef $api;
   $api = CFX5::CCLI::new_api_object();

   #parse the differences into the CCL database
   $errors = $api->parseCCLPaths(\@diffPathList);

   # Check for errors
   if (defined($errors)) {
     _debug("Difference Text is:\n\n", map { " $_\n" } @diffPathList);
     $errors =~ s!^! !gm;
     _error("Error constructing Command Language differences:\n", $errors);
     return();
   }

   # Extract the CCL for the differences
   $api->getExpandedCCL(\@output,0);

   # tack on a newline to the output for ease of printing
   return map { "$_\n" } @output;
}

1;
