#!/usr/bin/perl -Ilibs
use strict;

package API::Brand;

use API::Config;
our $Config = $API::Config::Config;
use lib $API::Config::Config->{'Website_libs'};

use Cache::Memcached::Fast;
use Image::Magick;
use MIME::Base64;
use MIME::Entity;
use WebService::Rackspace::CloudFiles;
use SOAP::Lite;
use HTML::Strip;
use base 'SOAP::Server::Parameters';

use ECS::Brand;
use ECS::Cache::BrandCache;
use ECS::format;
use ECS::SQL;
use ECS::Site;
use ECS::CDN::S3;
my $DBH = ECS::SQL::connect();
my $DBHr = ECS::SQL::connect('SLAVE');

my @columns = qw(
    brandID
    name
    description
    website
    phone
    mm_brandID
    address1
    city
    state
    zip
    address2
    country
    genuine
    marketSegment
    purpose
    turnerPreferred
    sdsStageLimit
    xoType
    oemBrand
	useAlternateProductSuggestion
        specialOrderMinimumLeadTime
        specialOrderMaximumUnitsSold
        specialOrder
    retailMarginFloor
    retailMarginFloorPercent
);

my @brandLogColumns = qw(
    website
    state
    mm_brandID
    city
    country
    name
    genuine
    description
    phone
    address1
    address2
    zip
    brandID
    marketSegment
    purpose
    logo 
    header_logo
    TMS.description
    sdsStageLimit
    xoType
    oemBrand
	useAlternateProductSuggestion
    turnerPreferred
    specialOrderMinimumLeadTime
    specialOrderMaximumUnitsSold
    specialOrder
    retailMarginFloor
    retailMarginFloorPercent
);

# update memcached and db
#---------------------------------------------------
sub add{
	my $ref = shift;
	my $input = shift;

    $input->{genuine} = ($input->{genuineCheckbox} || 0);
	$input->{oemBrand} = ($input->{oemBrandCheckbox} || 'NO');
	$input->{useAlternateProductSuggestion} = ($input->{useAlternateProductSuggestionCheckbox} || 'NO');
	my $result = {
		'success'	=> 1,
		'error'		=> undef,
		'update_DB'	=> $Config->{update_DB},
		'update_cache'	=> $Config->{update_cache},
		'ID' => undef
	};

	$input->{mm_brandID} = substr($input->{name},0,10) if($input->{mm_brandID} eq "Use Brand Name (10 Chars Max)");

    my @saveColumns = @columns;
	if($input->{has_logo}){
		push(@saveColumns,"width","height");
	}

	# No Errors, so insert
	# allow abbreviation on insert
	#---------------------------------------------------
	push(@saveColumns, "abbr");

	# always uppercase the abbreviation
	#---------------------------------------------------
	$input->{abbr} = uc $input->{abbr};

    my $qAbbr = ECS::SQL::quote({'DBH' => $DBH, 'value' => $input->{'abbr'}});
    my $sql = qq{
        SELECT
            1
        FROM brand
        WHERE
            abbr = $qAbbr
        LIMIT 1
    };
    my ($brandExists) = @{
        ECS::SQL::query({
            'DBH' => $DBHr,
            'sql' => $sql,
        })
        || []
    };

    if($brandExists) {
        $result->{'success'} = 0;
        $result->{'error'} = "Duplicate Abbreviation";
        return $result;
    }
	if($input->{hasHeaderLogo} eq 'YES'){
		push(@saveColumns,"hasHeaderLogo");
	}

    push(@saveColumns, "seName");
    $input->{'seName'} = ECS::format::toSeoUrl( $input->{'name'} );
    $input->{'seName'} =~ s/(,|"|\.|\')//g;

    if ( length( $input->{'sdsStageLimit'} ) == 0 ) {
        $input->{'sdsStageLimit'} = undef;
    }

    my %brandRowData;
    for my $col ( @saveColumns ) {
        $brandRowData{ $col } = $input->{ $col };
    }

	my $lastID = _insertBrandRow({
        'dbh' => $DBH,
        'rowData' => \%brandRowData,
    });

	if($lastID) {
		$result->{ID} = $lastID;
        $input->{ 'TMS.brandID' } = $lastID;
	} else {
		$result->{success} = 0;
		$result->{error} = "Unable to add record to DB.";
		return $result;
	}

    _setTmsFields( $input );

	# Update the Brand Names cache
	# IF we want to write to DB (Determined by API::Config)
	# --------------------------------------------------
	if ($Config->{update_cache}){
		if (!ECS::Cache::BrandCache::updateBrandIDs({
			DBH => $DBH,
			override => 1
		})){
			$result->{success} = 0;
			$result->{error} = "Unable to write the brand names cache.";
			return $result;
		};
	}
	logAddBrand($input);	
    return $result;
}

# edit api call
#---------------------------------------------------
sub edit{

	my $self = shift;
	my $input = shift;

    $input->{genuine} = ($input->{genuineCheckbox} || 0);
	$input->{oemBrand} = ($input->{oemBrandCheckbox} || 'NO');
	$input->{useAlternateProductSuggestion} = ($input->{useAlternateProductSuggestionCheckbox} || 'NO');
	my $result = {
		'success'	=> 1,
		'name'	=> undef,
		'has_logo' => 0,
		'hasHeaderLogo' => 'NO',
		'error'		=> undef,
		'update_DB'	=> $Config->{update_DB},
		'update_cache'	=> $Config->{update_cache}
	};

	$input->{mm_brandID} = substr($input->{name},0,10) if($input->{mm_brandID} eq "Use Brand Name (10 Chars Max)");

	my $sql = "SELECT * FROM brand WHERE brandID = " . ECS::SQL::quote({DBH=>$DBH, value=>$input->{editBrand}});
	my $rd = ECS::SQL::query( {DBH => $DBH, sql => $sql} );
	my $brand_original = {};
	$brand_original = $rd->[0] if ($rd);

    my $sqlTmsColumns = join ", ", @ECS::Brand::TMS_FIELDS;
    my $sqlGetTms = qq{
        SELECT
            $sqlTmsColumns
        FROM brand
        WHERE
            brandID = ?
    };
    my $tms = ECS::Site->fromName( "TMS" );
    my $sthGetTms = $tms->site_dbhr->prepare( $sqlGetTms );
    $sthGetTms->execute( $input->{ 'editBrand' } );
    my $tmsFields = $sthGetTms->fetchrow_hashref;
    for my $column ( @ECS::Brand::TMS_FIELDS ) {
        my $value = $tmsFields->{ $column };
        $brand_original->{ "TMS.$column" } = $value;
    }

    my @saveColumns = @columns;
	if($input->{has_logo}){
		push(@saveColumns,"width","height");
	}
	if($input->{hasHeaderLogo} eq 'YES'){
		push(@saveColumns,"hasHeaderLogo");
	}

	my $s3 = ECS::CDN::S3->new();
    my $container = 'static';
	

	if ($brand_original->{name} ne $input->{name} && $brand_original->{width}) {
		# Rename brand image
		#---------------------------------------------------
		rename($Config->{image_uploads}."/brands/".$brand_original->{name}.".gif", $Config->{image_uploads}."/brands/".$input->{name}.".gif");
		
		# upload new logo to cloud
		#---------------------------------------------------

			if ($Config->{write_cloud}) {
		
		my $object_key = "img/brands/" . $input->{name} . ".gif";
		my $file_path = $Config->{image_uploads} . "/brands/" . $input->{name} . ".gif";

		my $c_result = $s3->put_file( $s3->build_path( $container, $object_key),  $file_path, { 'Content-Type' => 'image/gif'});
		my $upload_var;  warn "the  variable here : $object_key";
	}

	}
	
	if ($brand_original->{name} ne $input->{name} && $brand_original->{hasHeaderLogo} eq "YES") {
		# Rename brand header image
		#---------------------------------------------------
		rename($Config->{image_uploads}."/brands_large/".$brand_original->{name}."_xlarge.gif", $Config->{image_uploads}."/brands_large/".$input->{name}."_xlarge.gif");
		if($Config->{write_cloud}){
		    my $object_key = "img/brands_large/" . $input->{name} . "_xlarge.gif";
   			my $file_path = $Config->{image_uploads} . "/brands_large/" . $input->{name} . "_xlarge.gif";

			my $c_result = $s3->put_file( $s3->build_path( $container, $object_key),  $file_path, { 'Content-Type' => 'image/gif'});
			my $upload_var;  warn "the  variable here : $object_key";
		# upload new header logo to cloud
		#---------------------------------------------------

		}
	}

	# If no abbreviation, allow updating abbreviation
	#---------------------------------------------------
	if (!$brand_original->{abbr}) {
		push(@saveColumns, "abbr");

		# always uppercase the abbreviation
		#---------------------------------------------------
		$input->{abbr} = uc $input->{abbr};
	}
	$input->{brandID} = $input->{editBrand};
    $input->{ 'TMS.brandID' } = $input->{ 'brandID' };
	$input->{description} = HTML::Strip->new->parse($input->{description});
	$input->{ 'TMS.description' } = HTML::Strip->new->parse( $input->{ 'TMS.description' } );
    if ( length( $input->{'sdsStageLimit'} ) == 0 ) {
        $input->{'sdsStageLimit'} = undef;
    }

	# No errors, so insert

    my %brandRowData;
    for my $col ( @saveColumns ) {
        $brandRowData{ $col } = $input->{ $col };
    }

    _updateBrandRow({
        'dbh' => $DBH,
        'brandID' => $input->{'brandID'},
        'rowData' => \%brandRowData,
    });

    _setTmsFields( $input );

    if ( $brand_original->{ 'oemBrand' } ne $input->{ 'oemBrand' } ) {
        _setProductOemTag( $input );
    }
    
    # hooray for 80 character line limits
    if ($brand_original->{'specialOrderMinimumLeadTime'} ne
            $input->{'specialOrderMinimumLeadTime'}
        || $brand_original->{'specialOrderMaximumUnitsSold'} ne
        $input->{'specialOrderMaximumUnitsSold'}) {
        _setSpecialOrderValues($input);
    }


    if ( $brand_original->{ 'turnerPreferred' } ne $input->{ 'turnerPreferred' } ) {
        _setProductTurnerPreferred( $input );
    }

	# Clear the cache for this Brand
	# IF update memcached (Determined by API::Config)
	# ---------------------------------------------
	if ($Config->{update_cache}){
		ECS::Cache::BrandCache::deleteBrand({
			key => 'brand_'.$input->{editBrand}
		});
		
		# If the Brand Name has changed, update the Brand Names cache
		#---------------------------------------------------
		if ($input->{name} ne $brand_original->{name}) {
			if(!ECS::Cache::BrandCache::updateBrandIDs({
				DBH => $DBH,
				override => 1
			})){
				$result->{success} = 0;
				$result->{error} = "Unable to edit the brand names cache.";
				return $result;
			};
		}
	}

	writeChangeLog($input, $brand_original);	
	return $result;
}

sub _setTmsFields {
    my ( $input ) = @_;

    my $tms = ECS::Site->fromName( "TMS" );
    
    my $sqlTmsColumns = join ", ", @ECS::Brand::TMS_FIELDS;
    my $sqlPlh = join ", ", ( "?" ) x @ECS::Brand::TMS_FIELDS;
    my @tmsUpdateColumns = grep { $_ ne "brandID" } @ECS::Brand::TMS_FIELDS;
    my $sqlUpdateTmsColumns = join ", ", map { "$_ = VALUES( $_ )" } @tmsUpdateColumns;
    my $sqlUpdateTms = qq{
        INSERT INTO brand
            ( $sqlTmsColumns )
        VALUES
            ( $sqlPlh )
        ON DUPLICATE KEY UPDATE
           $sqlUpdateTmsColumns
    };
    my $sthUpdateTms = $tms->site_dbh->prepare( $sqlUpdateTms );
    my @values = map { $input->{ "TMS.$_" } } @ECS::Brand::TMS_FIELDS;
    $sthUpdateTms->execute( @values );

    return;
}

sub _setProductOemTag {
    my ( $input ) = @_;

    my $sql = q{
        UPDATE product
        JOIN brand USING ( brandID )
        SET product.OEM = brand.oemBrand
        WHERE brandID = ?
    };
    my $sth = $DBH->prepare( $sql );
    return $sth->execute( $input->{ 'brandID' } );
}


=head2 _setSpecialOrderValues 

Set the special order parameters for a brand

Accepts: C<$input> hash containing values rom the brand admin add / edit form

Returns: C<1> on success, C<undef> on failure

=cut
sub _setSpecialOrderValues {
    my ( $input ) = @_;

    my $specialOrderMinimumLeadTime = $input->{ 'specialOrderMinimumLeadTime' };
    my $specialOrderMaximumUnitsSold = $input->{ 'specialOrderMaximumUnitsSold' };
    my $brandID = $input->{ 'brandID' };

    my $sql;
    $sql = q{
        UPDATE brand SET specialOrderMinimumLeadTime = ?, specialOrderMaximumUnitsSold = ?
        WHERE brandID = ?
    };

    my $sth = $DBH->prepare($sql);
    return $sth->execute($specialOrderMinimumLeadTime, $specialOrderMaximumUnitsSold, $brandID);

}


sub _setProductTurnerPreferred {
    my ( $input ) = @_;
	
	my ($siteName) =  'TMS';
	my $site = fromName ECS::Site( $siteName );
	 my %TABLES;
	$TABLES{ $_ } = (sprintf '%s.%s' => $site->prefix, $_) for qw/
		product
/;
 my $sql = qq{
UPDATE $TABLES{product} tmsProduct INNER JOIN product USING (productID) 
JOIN brand USING (brandID) 
SET tmsProduct.turnerPreferred = brand.turnerPreferred
WHERE brandID = ?
    };
    my $sth = $DBH->prepare( $sql );
    return $sth->execute( $input->{ 'brandID' } );

}
sub delete{
	my $self = shift;
	my $input = shift;

	my $sql = qq{
		SELECT name from brand
		WHERE brandID = ?
		};
	my $sth = $DBHr->prepare($sql);
	$sth->execute($input->{'deleteBrand'});
	my $brandName = $sth->fetchrow_array();
	
	my $result = {
		'success'	=> 1,
		'error'		=> undef,
		'update_DB'	=> $Config->{update_DB},
		'update_cache'	=> $Config->{update_cache}
	};
	
	# IF we want to write to DB (Determined by API::Config)
	# --------------------------------------------------
	if ($Config->{update_DB}){
		ECS::SQL::delete({
	        	DBH => $DBH, 
	        	table => 'brand',
	        	columns => [qw(brandID)],
	        	hash => {brandID=>$input->{'deleteBrand'}}
	    });
	}
			
	# Clear the cache for this Brand
	# IF update memcached (Determined by API::Config)
	# ------------------------------
	if ($Config->{update_cache}){
		ECS::Cache::BrandCache::deleteBrand({key => 'brand_'.$input->{'deleteBrand'}});
		
		# Update the Brand Names cache
		#---------------------------------------------------
		if(!ECS::Cache::BrandCache::updateBrandIDs({
			DBH => $DBH,
			override => 1
		})){
				$result->{success} = 0;
				$result->{error} = "Unable to update the brand names cache.";
				return $result;
		};
	}
    logSingleEntry($input, 'name','',$brandName);
	return $result;
}

sub deleteLogo{
	my $self = shift;
    my $input = shift;
	
	my $editBrand = $input->{'editBrand'}; #shift;
	
	my $result = {
		'success'	=> 1,
		'name'	=> undef,
		'error'		=> undef,
		'update_DB'	=> $Config->{update_DB},
		'update_cache'	=> $Config->{update_cache}
	};
	
	# IF we want to write to DB (Determined by API::Config)
	# --------------------------------------------------
	if ($Config->{update_DB}){	
		ECS::SQL::update({
				DBH => $DBH,
				table =>'brand',
				key =>'brandID',
				columns => [qw(width height)],
				hash => {width => undef, height=> undef, brandID=>$editBrand}
		});
	}
		
		my $sql = "SELECT name FROM brand WHERE brandID=" . ECS::SQL::quote({DBH=>$DBH, value=>$editBrand});
		my $rd = ECS::SQL::query( {DBH => $DBH, sql => $sql} );
		if(!$rd->[0]->{name}){
			$result->{success} = 0;
			$result->{error} = "Unable to update database!";
		}else{
		    logSingleEntry($input, 'Logo','','Delete Logo');
			unlink $Config->{image_uploads}."/brands/" .$rd->[0]->{name}.".gif";
			return $result;
		}
}

sub deleteHeaderLogo{
	my $self = shift;
    my $input = shift;
	
	my $editBrand = $input->{'editBrand'}; #shift;
		my $result = {
		'success'	=> 1,
		'name'	=> undef,
		'error'		=> undef,
		'update_DB'	=> $Config->{update_DB},
		'update_cache'	=> $Config->{update_cache}
	};
	
	# IF we want to write to DB (Determined by API::Config)
	# --------------------------------------------------
	if ($Config->{update_DB}){	
		ECS::SQL::update({
				DBH => $DBH,
				table =>'brand',
				key =>'brandID',
				columns => ['hasHeaderLogo'],
				hash => {'hasHeaderLogo' => 'NO', brandID => $editBrand}
		});
	}
	
		my $sql = "SELECT name FROM brand WHERE brandID=" . ECS::SQL::quote({DBH=>$DBH, value=>$editBrand});
		my $rd = ECS::SQL::query( {DBH => $DBH, sql => $sql} );
	if(!$rd->[0]->{name}){
		$result->{success} = 0;
		$result->{error} = "Unable to update database!";
	}else{
	    logSingleEntry($input, 'Header Logo','','Delete Header Logo');
		unlink $Config->{image_uploads}."/brands_large/" .$rd->[0]->{name}."_xlarge.gif";
		$result->{success} = 1;
	}
		return $result;
}

sub logo{
	my $self = shift;
	my $input = shift;
	
	my $result = {
		'success'	=> 1,
		'update_DB'	=> $Config->{update_DB},
		'update_cache'	=> $Config->{update_cache},
		'write_cloud'	=> $Config->{write_cloud},
		'error'		=> undef,
		'response'	=> {
			'has_logo'	=> $input->{has_logo},
			'format'	=> $input->{format},
			'logo'		=> $input->{logo},
			'errorLogo'	=> $input->{errorLogo},
			'html'		=> $input->{html},
			'error'		=> $input->{error},
		}
	};

	my $s3 = ECS::CDN::S3->new();
    my $container = 'static';

    my $envelope = pop;
	
	# Upload image to image_uploads when write_image is true (API::Config)
	# ------------------------------------------------------------------
	if($Config->{write_image}){
		open(my $of, ">$Config->{image_uploads}/brands/$input->{filename}") || die "Cannot open file for writing ($Config->{image_uploads}/brands/$input->{filename})";#$write_file");
			my @parts = $envelope->parts();
			my $part = $parts[0]->[0];
			print $of $part->bodyhandle->as_string;
		close($of);
	}
	# Get details about image for processing
	#---------------------------------------------------
	my $image = Image::Magick->new;
	my ($width, $height, $size, $format) = $image->Ping($Config->{image_uploads} . "/brands/" . $input->{filename}) or die "Cannot ping logo image";
	$result->{'response'}->{'width'} = $width;
	$result->{'response'}->{'height'} = $height;

	if( ($format ne "GIF") || ($height > 28) ) {
		$result->{error} = "Brand logo must be a .gif that is 28 pixels high or less.";
		$result->{response}->{has_logo} = 0;
		$result->{success} = 0;
	} else {
		$result->{response}->{has_logo} = 1;
		$result->{success} = 1;
	}
	# Upload logo to AWS cloud's static container in "/img/brands_large"
	# ------------------------------------------------------------------

	if ($Config->{write_cloud} && $result->{success}) {
		    my $object_key = "img/brands/" . $input->{name} . ".gif";
   			my $file_path = $Config->{image_uploads} . "/brands/" . $input->{name} . ".gif";

			my $c_result = $s3->put_file( $s3->build_path( $container, $object_key),  $file_path, { 'Content-Type' => 'image/gif'});
			my $upload_var;  warn "the  variable here : $object_key";
		# upload new header logo to cloud


}


	return $result;
}

sub headerLogo{
 	my $self = shift;
	my $input = shift;

    die "brandName required" unless defined $input->{'brandName'};

	my $result = {
		'success'	=> 1,
		'update_DB'	=> $Config->{update_DB},
		'update_cache'	=> $Config->{update_cache},
		'write_cloud'	=> $Config->{write_cloud},
		'error'		=> undef,
		'response'	=> {
			'has_header_logo'	=> $input->{has_header_logo},
			'format'	=> $input->{format},
			'headerLogo'=> $input->{logo},
			'html'		=> $input->{html},
			'error'		=> $input->{error},
		}
	};

    my $logoURI = ECS::Brand::brandNameToHeaderLogoURI( $input->{'brandName'} );

	my $s3 = ECS::CDN::S3->new();
    my $container = 'static';

	my $envelope = pop;
    my $localLogoPath = "$Config->{image_uploads}/brands_large/$input->{filename}";

	# Upload image to image_uploads when write_image is true (API::Config)
	# ------------------------------------------------------------------
	if($Config->{write_image}){
		open(my $of, ">$localLogoPath")
            || die "Cannot open file for writing ($localLogoPath)";
		my @parts = $envelope->parts();
		my $part = $parts[0]->[0];
		print $of $part->bodyhandle->as_string;
		close($of);
	}
	# Get details about image for processing
	#---------------------------------------------------
	my $image = Image::Magick->new;
	my ($width, $height, $size, $format) = $image->Ping( $localLogoPath )
        or die "Cannot ping header logo image";

	if( ($format ne "GIF") || ($height < 50) ) {
		$result->{error} = "Brand header logo must be a .gif that is at least 50 pixels high.";
		$result->{response}->{hasHeaderLogo} = "NO";
		$result->{success} = 0;
	} else {
		$result->{response}->{hasHeaderLogo} = "YES";
		$result->{success} = 1;
	}
	# Upload logo to AWS cloud's static container in "/img/brands_large"
	# ------------------------------------------------------------------
		if($Config->{write_cloud} && $result->{success}){
			my $objectName = $logoURI->path;
			$objectName = substr($objectName, 1);

				my $object_key = $objectName;
				my $file_path = $localLogoPath;

            # this doesn't need build_path because brandNameToHeaderLogoURI
            # already has the container name included
            my $c_result = $s3->put_file( $object_key,  $file_path, { 'Content-Type' => 'image/gif'});

        # Remove leading slash. important. misleading if forgotten. ugh

	}
	return $result;
}

sub writeChangeLog {
	my $input = shift;
	my $original = shift;
	
    my $marketSegments = ECS::Cache::BrandCache::getMarketSegments({DBH => $DBH});
	$input->{brand}->{'marketSegment'} =  $marketSegments->{$input->{marketSegment}}->{'display'} if(!$input->{brand}->{'marketSegment'});

    $input->{genuine} = ($input->{genuineCheckbox} || 0);
	$original->{genuine} = ($original->{genuine} || 0);

	foreach my $key (@brandLogColumns) {
	    my $inputKeyValue = $input->{$key};
	    $inputKeyValue = $input->{brand}->{$key} if ($key eq 'marketSegment');
   		if ($inputKeyValue ne $original->{$key}) {
       		my $sql = qq{
        		INSERT INTO
	        		brandChangeLog (brandID, employeeID, field, oldValue, newValue)
		        VALUES (?,?,?,?,?)
		        };
	        my $changeLog = $DBH->prepare($sql);
	        $changeLog->execute($input->{'brandID'},$input->{'employeeID'}, $key, $original->{$key}, $inputKeyValue);
	    }
	}
}

sub logAddBrand {
	my $input = shift;

	my $original;
	foreach my $key (@brandLogColumns) {
	    $original->{$key} = '';
    }
	my $sql = qq{
		SELECT brandID FROM brand
		WHERE name = ?
	};
	my $sth = $DBHr->prepare($sql);
	$sth->execute($input->{'name'});
	$input->{'brandID'} = $sth->fetchrow_array();

    logSingleEntry($input,'name','Add Brand',$input->{'name'});
    writeChangeLog($input,$original);
}

sub logSingleEntry {
	my ($input,$field,$oldValue,$newValue) = @_;
	
	my $sql = qq{
		INSERT INTO
			brandChangeLog (brandID, employeeID, field, oldValue, newValue)
		VALUES (?,?,?,?,?)
		};
	my $changeLog = $DBH->prepare($sql);
	$changeLog->execute($input->{'editBrand'},$input->{'employeeID'}, $field, $oldValue, $newValue);
}

sub _insertBrandRow {
    my ( $p ) = @_;

    my $dbh = $p->{'dbh'}
        or die "dbh required";
    my $rowData = $p->{'rowData'}
        or die "rowData required";

    my @cols = keys %{ $rowData };

    my $sth = $dbh->prepare(
        "INSERT INTO brand"
        ." SET ".join( ', ', map { $_." = ?" } @cols )
    );

    $sth->execute(
        map( $rowData->{ $_ }, @cols ),
    );

    return $sth->{'mysql_insertid'};
}

sub _updateBrandRow {
    my ( $p ) = @_;

    my $dbh = $p->{'dbh'}
        or die "dbh required";
    my $brandID = $p->{'brandID'}
        or die "brandID required";
    my $rowData = $p->{'rowData'}
        or die "rowData required";

    my @cols = keys %{ $rowData };

    my $sth = $dbh->prepare(
        "UPDATE brand SET ".join( ', ', map { $_." = ?" } @cols )
        ." WHERE brandID = ?"
    );

    $sth->execute(
        map( $rowData->{ $_ }, @cols ),
        $brandID,
    );

    return;
}
