#!/usr/local/bin/perl
#
# update - MiniVend database updater
#
# $Id: update,v 1.4 1998/03/21 12:18:26 mike Exp mike $
#
# This program is largely based on Vend 0.2
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
#
# Portions from Vend 0.3
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
#
# Enhancements made by and
# Copyright 1996-1998 by Michael J. Heins <mikeh@minivend.com>
#
# See the file 'Changes' for information.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

BEGIN {

    eval {
        require 5.004;
        require FindBin;
        1 and $Global::VendRoot = "$FindBin::RealBin";
        1 and $Global::VendRoot =~ s/.bin$//;
    };
	($Global::VendRoot = $ENV{MINIVEND_ROOT})
		if defined $ENV{MINIVEND_ROOT};
	$Global::VendRoot = $Global::VendRoot || '/home/minivend';
}
### END CONFIGURABLE VARIABLES

sub dontwarn { $FindBin::RealBin; }

$Global::ConfigFile = 'minivend.cfg';
$Global::ErrorFile = "$Global::VendRoot/error.log";

use lib "$Global::VendRoot/lib";

my $DEBUG = 0;

use strict;
use Fcntl;

#select a DBM

BEGIN {
	$Global::GDBM = $Global::DB_File = 0;
    AUTO: {
        last AUTO if
            (defined $ENV{MINIVEND_DBFILE} and $Global::DB_File = 1);
        last AUTO if
			(defined $ENV{MINIVEND_NODBM});
        eval {require GDBM_File and $Global::GDBM = 1} ||
        eval {require DB_File and $Global::DB_File = 1};
    }
	if($Global::GDBM) {
		require Vend::Table::GDBM;
		import GDBM_File;
		$Global::GDBM = 1;
	}
	elsif($Global::DB_File) {
		require Vend::Table::DB_File;
		import DB_File;
		$Global::DB_File = 1;
	}
	else {
		die "No DBM defined! Update not designed to work with mSQL.\n";
	}
}

use Vend::Config;
use Vend::Data;

$Vend::Cfg = {};

my $Name = 'products';
my $Directory;

my $USAGE = <<EOF;
usage: update -c catalog [-n name] \\
            -f field [-f field1 -f field2 ...] -k key value [value1 value2 ...]
    or

usage: update -c catalog -i inputfile [-n name]

Options:

  -c catalog    Catalog name as defined in minivend.cfg.
  -f field      Field name(s) in database. If multiple fields are specified,
                multiple corresponding values must be supplied.  Use '' to
                set to the empty string.
  -i file       Input file to add entries to an existing database. (Must
                be in same format/order as existing database.)
  -k key        Key (item code) to be updated.
  -n name       Database name as defined in catalog.cfg (default products).

If specifying a subcatalog database, make sure it is defined in the
subcatalog definition.  If it is in the base catalog, use that catalog
as the parameter for the -c directive.
EOF

my ($Inputfile, $Key, @Fields, @Values);
my ($Catalog,$delimiter,$db);

GETOPT: {

	if($ARGV[0] eq '-c') {
		shift(@ARGV);
		$Catalog = shift(@ARGV);
		redo GETOPT;
	}
	elsif($ARGV[0] eq '-d') {
		shift(@ARGV);
		$Directory = shift(@ARGV);
		redo GETOPT;
	}
	elsif($ARGV[0] eq '-n') {
		shift(@ARGV);
		$Name = shift(@ARGV);
		redo GETOPT;
	}
	elsif($ARGV[0] eq '-k') {
		shift(@ARGV);
		$Key = shift(@ARGV);
		redo GETOPT;
	}
	elsif($ARGV[0] eq '-i') {
		shift(@ARGV);
		$Inputfile = shift(@ARGV);
		redo GETOPT;
	}
	elsif($ARGV[0] eq '-f') {
		shift(@ARGV);
		push(@Fields, shift @ARGV); 
		redo GETOPT;
	}

} # END GETOPT

die $USAGE unless defined $Catalog;

push @Values, @ARGV;

if(@Fields and ! @Values) {
	die $USAGE . "\n";
}
elsif (scalar(@Fields) != scalar(@Values) ) {
	die "Number of fields and number of values don't match.\n" . $USAGE . "\n";
}
elsif ((@Fields or @Values) and defined $Inputfile) {
	die "No field or value arguments accepted when inputting from a file.\n" .
	$USAGE . "\n";
}
elsif (@Fields and ! $Key) {
	die $USAGE . "\n";
}
elsif (!defined $Inputfile and ! @Fields and !@Values) {
	die $USAGE . "\n";
}

my($name,$dir,$param,$subcat,$subconfig);
chdir $Global::VendRoot;
open(GLOBAL, $Global::ConfigFile) or
    die "No global configuration file? Aborting.\n";
while(<GLOBAL>) {
    next unless /^\s*(sub)?catalog\s+$Catalog\s+/i;
    $subcat = $1 || '';
    chomp;
    s/^\s+//;
    unless($subcat) {
        (undef,$name,$dir,$param) = split /\s+/, $_, 4;
    }
    else {
        (undef,$name,$subconfig,$dir,$param) = split /\s+/, $_, 5;
    }
    last;

}
close GLOBAL;

global_config();

chdir $dir or die "Couldn't change directory to $dir: $!\n";

$Vend::Cfg = config($name, $dir, "$dir/etc", ($subconfig || undef));

die "Problems with config.\n" unless defined $Vend::Cfg;

$Vend::Cfg->{DataDir} = $Directory
	if defined $Directory;

die "Bad data directory $Vend::Cfg->{DataDir} -- doesn't exist.\n$USAGE\n"
	unless -d $Vend::Cfg->{DataDir};

die "Bad database $Name -- doesn't exist.\n\n$USAGE\n"
	unless
	ref
	($db = $Vend::Cfg->{Database}->{$Name});

$Vend::WriteDatabase{$Name} = 1;

my $ref = import_database($db->{'file'}, $db->{'type'}, $Name);

die "Bad import of database $Name from catalog $Catalog: $!\n"
	unless defined $ref;

unless($ref->record_exists($Key)) {
	die "Key $Key not found in database $Name.\n";
}

my ($key,$field,@fields);

if (! defined $Inputfile ) {
	foreach $field (@Fields) {
		unless ( defined $ref->test_column($field) ) {
			die "$field is not a column in the database.\n";
		}
		$ref->set_field($Key, $field, shift(@Values));
	}
}
else {
	open INPUT, $Inputfile or die "Couldn't open input file $Inputfile: $!\n";
	while(<INPUT>) {
		chomp;
		s/[\r\cZ]+//;
		($key,@fields) = split /\t/, $_;
		$ref->set_row($key, @fields);
	}
	close INPUT;
}

close_database();

