
package HTML::WebMake::CGI::Site;

use strict;
use HTML::WebMake::CGI::CGIBase;
use HTML::WebMake::CGI::CVS;
use HTML::WebMake::Main;
use File::Basename;

use vars	qw{
  	@ISA $POST_BUILD_TMPL $ERRORS_TMPL $BUILT_OK_TMPL 
	$CVS_UPDATE_TMPL $POST_CVS_COMMIT_TMPL $PRE_CVS_COMMIT_TMPL
        $PAGE_TITLE $PAGE_HEADER
};

@ISA = qw(HTML::WebMake::CGI::CGIBase);

###########################################################################

$PAGE_TITLE = q{ Edit Site "__FNAME__" };
$PAGE_HEADER = q{ Edit Site };

$POST_BUILD_TMPL = q{
__ERRORS__

__FORM__
};

$BUILT_OK_TMPL = qq{
    <p>
    Built the site successfully.
    </p>

    <ul>
    <li>
    <a href="__REINVOKE__Commit=1__">Check in</a> the changes you've made
    </li>

    <li>
    <a href="__REINVOKE__site=1__">Carry on editing</a> the WebMake file
    </li>
    </ul>
};

$ERRORS_TMPL = qq{
    <p>
    Some errors were encountered!
    </p>

    <ul>
    <li>
    <a href="__REINVOKE__site=1__">Re-edit</a> the WebMake file
    </li>
    <li>
    <a href="__REINVOKE__Commit=1__">Ignore them</a> and check-in the
    changes you've made
    </li>
    </ul>
};

$CVS_UPDATE_TMPL = qq{

    __CVS_UPDATE_OUTPUT__

    <p>
    Return to the
    <a href="__REINVOKE__site=1__">WebMake file</a>.
    </p>
};

$PRE_CVS_COMMIT_TMPL = qq{
    <p>
    A message is required to perform the CVS commit.
    Please enter some text describing your changes here.
    </p>

    <textarea name=cvsmsg rows=5 columns=75 class="wm_textarea"></textarea>
    <br />
    __SUBMIT__
};

$POST_CVS_COMMIT_TMPL = qq{

    __CVS_COMMIT_OUTPUT__

    <p>
    If the CVS commit was successful, return to the
    <a href="__REINVOKE__site=1&cvsadd=&cvsaddbin=&cvsrm=&cvsrmdir=__">
    WebMake file</a> here.
    </p>

    <p>
    If there were errors, and you wish to keep the list
    of files that need to be added and deleted, use
    <a href="__REINVOKE__site=1__">this link</a>.
    </p>
};#"

###########################################################################

sub new {
  my $class = shift;
  $class = ref($class) || $class;
  my $self = $class->SUPER::new (@_);

  $self->{page_title} = $PAGE_TITLE;
  $self->{page_header} = $PAGE_HEADER;
  $self->{no_filename_needed} = 1;

  bless ($self, $class);
  $self;
}

###########################################################################

sub subrun {
  my $self = shift;
  my $q = $self->{q};

  $self->{filename} = $self->{wmkfile};
  if ($q->param ('Commit')) {
    $self->write_commit_page ();
  } elsif ($q->param ('Update')) {
    $self->write_update_page ();
  } elsif ($q->param ('build')) {
    $self->write_build_page ();
  } elsif ($q->param ('editid')) {
    $self->write_editid_page ();
  } else {
    $self->write_list_page ();
  }
}

sub write_list_page
{
  my $self = shift;
  my $q = $self->{q};

  return '' unless $self->read_wmk_file ($self->{wmkfile});
  my $dir = File::Basename::dirname ($self->{wmkfile});

  my $form = qq{
    <table>
  };
  my $wmkf = $self->{q}->escape ($self->{wmkfile});
  my $path;

  foreach my $item (@{$self->{items}}) {
    $form .= qq{
	<tr><td valign=top width=80%>
	<strong>$item->{name}</strong>
    };

    $form .= q{ <ul> };
    foreach my $attr (sort keys %{$item->{attrs}}) {
      next if ($attr eq 'name');
      my $val = $item->{attrs}->{$attr};
      $form .= qq{
	  <li>
	  $attr = $val
	  </li>
      };
    }
    $form .= q{ </ul> };

    # my $re = $item->{origtagregexp}; $re =~ s/</&lt;/gs; $form .= $re;

    $form .= qq{ </td><td width=20%> };

    my $editui = $item->{editui};
    my $data = $item->{edituidata};
    if ($editui == $HTML::WebMake::WmkFile::CGI_EDIT_AS_DIR)
    {
      $path = $self->{q}->escape ($self->makepath ($dir, $data));
      $form .= qq{ <a href="__REINVOKE__wmkf=${wmkf}\&dir=${path}__">[Browse Source Dir]</a> }; #"
    }
    elsif ($editui == $HTML::WebMake::WmkFile::CGI_EDIT_AS_WMKFILE)
    {
      $path = $self->{q}->escape ($self->makepath ($dir, $data));
      $form .= qq{ <a href="__REINVOKE__wmkf=${path}\&site=1__">[Edit]</a> }; #"
    }
    elsif ($editui == $HTML::WebMake::WmkFile::CGI_EDIT_AS_TEXT)
    {
      my $id = $item->{id};
      my $name = $q->escape ($item->{name});
      my $nametext = $item->{name};
      $nametext =~ s/[\"\']//gs; $nametext = $q->escape ($nametext);

      $form .= qq{ <a href="__REINVOKE__wmkf=${wmkf}}.
      		qq{\&editblock=1\&id=${id}\&f=${nametext}__">[Edit]</a> };#"

      # use a form here, because we may need to pass in the entire text of the
      # data item.  (I prefer links like the [Browse] items above as they're
      # bookmarkable, but forms can handle big data items using POST.) 
      #
      # Now off: better to use a link, in case the item text is changed
      # between viewing and editing.
      #
      # $form .= $q->startform()
      # . $q->submit (-name=>'Edit',-value=>'Edit')
      # . $q->hidden (-name=>'editblock', -value=>'1')
      # . $q->hidden (-name=>'id', -value=>$id)
      # . $q->hidden (-name=>'filetext', -value=>$data)
      # . $q->hidden (-name=>'f', -value=>$nametext)
      # . $self->std_cgi_hidden_items ($q)
      # . $q->endform();
    }
    elsif ($editui == $HTML::WebMake::WmkFile::CGI_NON_EDITABLE)
    {
      $form .= qq{ <em>[Not editable]</em> };
    }

    $form .= qq{
	</td></tr>
    };
  }

  $path = $self->{q}->escape ($self->{wmkfile});
  $form .= qq{
    </table>
    <p>
    <a href="__REINVOKE__wmkf=${wmkf}\&edit=1\&nometas=1\&f=${path}__">
    [Edit This XML File As Text]</a>
    </p>
  };#"
  $form;
}

###########################################################################

sub modify_text_item {
  my ($self, $newtext) = @_;
  my $q = $self->{q};

  $self->{wmkfile} = $q->param ('wmkf');

  if (!$self->read_wmk_file ($self->{wmkfile})) {
    return "Could not read WebMake file \"$self->{wmkfile}\".";
  }

  my $id = $q->param ('saveasid');
  my $gotit = undef;

  foreach my $item (@{$self->{items}}) {
    next unless ($item->{id} eq $id);

    my $tag = $item->{tag};
    my $block = "<".$tag;
    foreach my $attr (sort keys %{$item->{attrs}}) {
      $block .= " ".$attr."=\"".$item->{attrs}->{$attr}."\"";
    }
    $block .= ">".$newtext."</".$tag.">";

    $self->{fulltext} =~ s/$item->{origtagregexp}/${block}/gs;
    $gotit = $item->{name};

    my $endf = $self->{file_base}."/".$self->{wmkfile};
    my $newf = $endf.".new";
    my $bakf = $endf.".bak";
    if (!open (FILE, ">".$newf)) {
      $self->warn ("cannot write to {WMROOT}/".$self->{wmkfile}.".new!");
      goto failed;
    }
    print FILE $self->{fulltext};
    if (!close FILE) {
      $self->warn ("cannot write to {WMROOT}/".$self->{wmkfile}.".new!");
      unlink $newf;
      goto failed;
    }

    rename ($endf, $bakf) or
	      $self->warn ("failed to rename old {WMROOT}/".$self->{wmkfile});
    rename ($newf, $endf) or
	      $self->warn ("failed to rename to {WMROOT}/".$self->{wmkfile});

    if ($self->{cvs_supported} && !$self->{cvs}->file_in_cvs ($endf)) {
      $self->cvs_add ($endf);
    } 
  }

  if ($gotit) {
    return "Modified $gotit successfully.";
  } else {
    return "Could not find that item in this file!";
  }

failed:
  return "Failed to modify $gotit!";
}

###########################################################################

sub write_build_page
{
  my $self = shift;
  my $q = $self->{q};
  my $form;

  my $file = $self->{wmkfile};
  my $dir = $self->mydirname();

  chdir ($self->{file_base}.'/'.$dir);
  return '' unless $self->read_wmk_file ($file);

  # hack: because WebMake uses stdout, print the std template here first,
  # then change the template.

  $self->{template} = $HTML::WebMake::CGI::CGIBase::BASIC_TMPL_TOP;
  $self->write_html_main("");
  $self->{template} = $HTML::WebMake::CGI::CGIBase::BASIC_TMPL_REST;

  chdir ($self->{file_base}.'/'.$dir);
  my $opts = {
    'html_logging' => 1
  };

  if ($q->param ('full')) {
    $opts->{'force_output'} = 1;
  }

  # make webmake issue warnings into the HTML
  local $SIG{__WARN__} = sub {
    $self->warn ($self->txt2html (@_));
  };

  eval {
    $self->{webmake} = new HTML::WebMake::Main ($opts);
    $self->{webmake}->setcachefile ("/tmp/webmake_cache/%u/%F");
    $self->{webmake}->readfile ($file);
    $self->{webmake}->make ();
  };

  if ($self->{webmake}->finish() == 0) {
    $form .= $BUILT_OK_TMPL;
  } else {
    $form .= $ERRORS_TMPL;
  }

  $form;
}

###########################################################################

sub write_update_page {
  my $self = shift;
  return $self->subst_template ($CVS_UPDATE_TMPL,
		 { CVS_UPDATE_OUTPUT => $self->{cvs}->cvs_update() });
}

###########################################################################

sub write_commit_page {
  my $self = shift;
  my $text = '';

  my $q = $self->{q};
  my $cvsmsg = $q->param ('cvsmsg');

  if (!defined $cvsmsg || $cvsmsg eq '') {
    my $buttons = $q->submit(-name=>'Commit',-value=>'Commit')
		. $q->hidden(-name=>'f',-value=>$self->{wmkfile})
		. $self->std_cgi_hidden_items($q)
		. $q->endform();

    $text .= $q->startform(-method => 'GET')
	. $self->subst_template ($PRE_CVS_COMMIT_TMPL, { SUBMIT => $buttons });
    return $text;
  }

  $cvsmsg = HTML::WebMake::CGI::CGIBase::mksafe ($cvsmsg);
  $cvsmsg .= " (commit by ".$q->remote_user()." using webmake.cgi)";

  my $cvs = $self->{cvs};
  my $cvstext = $cvs->do_cvs_deletes();
  $cvstext .= $cvs->do_cvs_adds();
  $cvstext .= $cvs->cvs_commit($cvsmsg);

  return $self->subst_template ($POST_CVS_COMMIT_TMPL,
  			{ CVS_COMMIT_OUTPUT => $cvstext });
}

###########################################################################

1;
