package VC7WorkspaceCreator;

# ************************************************************
# Description   : A VC7 Workspace Creator
# Author        : Chad Elliott
# Create Date   : 5/14/2002
# ************************************************************

# ************************************************************
# Pragmas
# ************************************************************

use strict;

use VC7ProjectCreator;
use WorkspaceCreator;

use vars qw(@ISA);
@ISA = qw(WorkspaceCreator);

# ************************************************************
# Data Section
# ************************************************************

my(%guids) = ('cplusplus' => '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
              'csharp'    => 'FAE04EC0-301F-11D3-BF4B-00C04F79EFBC',
              'vb'        => 'F184B08F-C81C-45F6-A57F-5ABD9991F28F',
              'website'   => 'E24C65DC-7377-472B-9ABA-BC803B73C61A',
             );

# ************************************************************
# Subroutine Section
# ************************************************************

sub compare_output {
  #my($self) = shift;
  return 1;
}


sub crlf {
  my($self) = shift;
  return $self->windows_crlf();
}


sub workspace_file_name {
  my($self) = shift;
  return $self->get_modified_workspace_name($self->get_workspace_name(),
                                            '.sln');
}


sub pre_workspace {
  my($self) = shift;
  my($fh)   = shift;
  my($crlf) = $self->crlf();

  print $fh 'Microsoft Visual Studio Solution File, Format Version 7.00', $crlf,
            '#', $crlf,
            '# VC7WorkspaceCreator.pm,v 1.26 2006/06/22 12:25:25 elliott_c Exp', $crlf,
            '#', $crlf,
            '# This file was generated by MPC.  Any changes made directly to', $crlf,
            '# this file will be lost the next time it is generated.', $crlf,
            '#', $crlf,
            '# MPC Command:', $crlf,
            "# $0 @ARGV", $crlf;
}


sub print_inner_project {
  #my($self)  = shift;
  #my($fh)    = shift;
  #my($gen)   = shift;
  #my($pguid) = shift;
  #my($deps)  = shift;
  #my($name)  = shift;
}


sub print_configs {
  my($self)    = shift;
  my($fh)      = shift;
  my($configs) = shift;
  my($crlf)    = $self->crlf();
  my($count)   = 0;

  foreach my $key (sort keys %$configs) {
    print $fh "\t\tConfigName.$count = $key$crlf";
    $count++;
  }
}


sub print_dependencies {
  my($self) = shift;
  my($fh)   = shift;
  my($gen)  = shift;
  my($list) = shift;
  my($pjs)  = shift;
  my($crlf) = $self->crlf();

  ## I hate to add yet another loop through all the projects, but
  ## we must have some way to map plain project names to guids.
  my(%name_to_guid_map) = ();
  foreach my $project (@$list) {
    my($name, $deps, $guid) = @{$$pjs{$project}};
    $name_to_guid_map{$name} = $guid;
  }

  ## Project Dependencies
  print $fh "\tGlobalSection(ProjectDependencies) = postSolution$crlf";
  foreach my $project (@$list) {
    my($name, $rawdeps, $project_guid) = @{$$pjs{$project}};
    my($deps) = $self->get_validated_ordering($project);
    if (defined $$deps[0]) {
      my($i) = 0;
      foreach my $dep (@$deps) {
        my($guid) = $name_to_guid_map{$dep};
        if (defined $guid) {
          print $fh "\t\t{$project_guid}.$i = {$guid}$crlf";
          $i++;
        }
      }
    }
  }
  print $fh "\tEndGlobalSection$crlf";
}


sub write_comps {
  my($self)     = shift;
  my($fh)       = shift;
  my($gen)      = shift;
  my($projects) = $self->get_projects();
  my($pjs)      = $self->get_project_info();
  my(@list)     = sort @$projects;
  my($crlf)     = $self->crlf();

  ## I hate to add yet another loop through all the projects, but
  ## we must have some way to map plain project names to guids.
  my(%name_to_guid_map) = ();
  foreach my $project (@list) {
    my($name, $deps, $guid) = @{$$pjs{$project}};
    $name_to_guid_map{$name} = $guid;
  }

  ## Project Information
  foreach my $project (@list) {
    my($name, $rawdeps, $guid, $language) = @{$$pjs{$project}};
    my($pguid) = $guids{$language};
    my($deps) = $self->get_validated_ordering($project);
    ## Convert all /'s to \
    my($cpy) = $project;
    $cpy =~ s/\//\\/g;
    print $fh "Project(\"{$pguid}\") = \"$name\", \"$cpy\", \"{$guid}\"$crlf";
    $self->print_inner_project($fh, $gen, $guid, $deps, $name, \%name_to_guid_map);
    print $fh "EndProject$crlf";
  }

  print $fh "Global$crlf",
            "\tGlobalSection(",
            $self->get_solution_config_section_name(),
            ") = preSolution$crlf";

  my(%configs) = ();
  foreach my $project (@list) {
    my($name, $deps, $pguid, $lang, @cfgs) = @{$$pjs{$project}};
    foreach my $cfg (@cfgs) {
      $configs{$self->get_short_config_name($cfg)} = $cfg;
    }
  }
  $self->print_configs($fh, \%configs);
  print $fh "\tEndGlobalSection$crlf";

  ## Print dependencies if there are any
  $self->print_dependencies($fh, $gen, \@list, $pjs);

  ## Project Configuration Names
  print $fh "\tGlobalSection(",
            $self->get_project_config_section_name(),
            ") = postSolution$crlf";

  ## See if there is an 'Any CPU' configuration
  my($anycpu) = undef;
  foreach my $key (keys %configs) {
    if (index($key, 'Any CPU') >= 0) {
      $anycpu = $key;
      $anycpu =~ s/^.*\|//;
      last;
    }
  }

  foreach my $project (@list) {
    my($name, $deps, $pguid, $lang, @cfgs) = @{$$pjs{$project}};
    my($first_cfg)   = undef;
    my($last_cfg)    = '.NET';
    my(%all_configs) = %configs;
    my($settings)    = '';
    foreach my $cfg (sort @cfgs) {
      my($c) = $self->get_short_config_name($cfg);
      $first_cfg = $cfg if (!defined $first_cfg);
      $last_cfg = $cfg;
      $settings .= "\t\t{$pguid}.$c.ActiveCfg = $cfg$crlf" .
                   "\t\t{$pguid}.$c.Build.0 = $cfg$crlf";
      delete $all_configs{$c};
    }

    ## If this is a mixed language workspace, we need to explicitly
    ## enable the building of the non-C++ projects when any platform
    ## other than Any CPU/.NET is selected.
    if (index($last_cfg, '.NET') >= 0 || index($last_cfg, 'Any CPU') >= 0) {
      $last_cfg =~ s/^.*\|//;
      foreach my $c (sort keys %configs) {
        if (defined $all_configs{$c}) {
          ## Get the long configuration name and replace the platform
          ## with the last platform (non-C++ platform)
          my($config) = $all_configs{$c};
          $config =~ s/\|.*/\|$last_cfg/;

          ## Enable the building of this project under all the other
          ## configurations (e.g. Win32, x64, etc.)
          print $fh "\t\t{$pguid}.$c.ActiveCfg = $config$crlf",
                    "\t\t{$pguid}.$c.Build.0 = $config$crlf";
        }
        else {
          print $fh "\t\t{$pguid}.$c.ActiveCfg = $configs{$c}$crlf",
                    "\t\t{$pguid}.$c.Build.0 = $configs{$c}$crlf";
        }
      }
    }
    else {
      if (defined $anycpu) {
        my(%printed) = ();
        foreach my $cfg (sort @cfgs) {
          my($c) = $self->get_short_config_name($cfg);
          my($any) = $c;
          $any =~ s/\|.*/\|$anycpu/;
          if (!defined $printed{$any}) {
            $printed{$any} = 1;
            print $fh "\t\t{$pguid}.$any.ActiveCfg = $first_cfg$crlf";
          }
          print $fh "\t\t{$pguid}.$c.ActiveCfg = $cfg$crlf",
                    "\t\t{$pguid}.$c.Build.0 = $cfg$crlf";
        }
      }
      else {
        print $fh $settings;
      }
    }
  }
  print $fh "\tEndGlobalSection$crlf";

  $self->print_additional_sections($fh);

  print $fh "EndGlobal$crlf";
}


sub get_short_config_name {
  my($self) = shift;
  my($cfg)  = shift;
  $cfg =~ s/\|.*//;
  return $cfg;
}


sub get_solution_config_section_name {
  #my($self) = shift;
  return 'SolutionConfiguration';
}


sub get_project_config_section_name {
  #my($self) = shift;
  return 'ProjectConfiguration';
}


sub print_additional_sections {
  my($self) = shift;
  my($fh)   = shift;
  my($crlf) = $self->crlf();

  print $fh "\tGlobalSection(ExtensibilityGlobals) = postSolution$crlf",
            "\tEndGlobalSection$crlf",
            "\tGlobalSection(ExtensibilityAddIns) = postSolution$crlf",
            "\tEndGlobalSection$crlf";
}


1;
