# Copyright 1999-2016. Parallels IP Holdings GmbH. All Rights Reserved.
package SiteApp::SiteApp;

use strict;

use Logging;
use PleskVersion;


##################################################
# Parameters:
# $site_application_id, $dbh
##################################################
sub new
{
  my $class = shift;

  my $self = {};
  bless($self, $class);

  $self->{id} = shift;
  $self->{dbh} = shift;

  $self->{SiteApp}    = {};
  $self->{Parameters} = {};
  $self->{Resources}  = {};
  $self->{Package}    = {};
  $self->{htdocs}  = [];
  $self->{cgi_bin} = [];

  my $sql = "SELECT * FROM SiteApps WHERE id=?";
  if (!$self->{dbh}->execute_rownum($sql, $self->{id})) {
    $self->{dbh}->finish();
    $self->_sqlError('Can not find Site Application in the database');
    return $self;
  }

  if ( my $hashPtr = $self->{dbh}->fetchhash() ) {
    $self->{SiteApp} = $hashPtr;
  }
  $self->{dbh}->finish();

  $self->_getParams();
  $self->_getLinkedResources();
  $self->_getPackageSpec();
  $self->_getHtdocsFiles();
  $self->_getCgibinFiles();

  return $self;
}

sub getName
{
  my SiteApp $self = shift;
  return $self->{Package}{'name'};
}

sub getVersion
{
  my SiteApp $self = shift;
  return $self->{Package}{'version'};
}

sub getRelease
{
  my SiteApp $self = shift;
  return $self->{Package}{'release'};
}

sub getDescription
{
  my SiteApp $self = shift;
  return $self->{Package}{'description'};
}

sub isCommercial
{
  my SiteApp $self = shift;
  return ($self->{Package}{'access_level'} & 1) != 0;
}

sub isIntegrated
{
  my SiteApp $self = shift;
  return 'true' eq $self->{Package}{'integrated'};
}

sub encodedParams
{
  my SiteApp $self = shift;
  return 0;
}

# Returns %hash
sub getParams
{
  my SiteApp $self = shift;
  return $self->{Parameters};
}

# Returns @list
sub getDatabases
{
  my SiteApp $self = shift;
  if (exists($self->{Resources}{'database'})) {
    return @{$self->{Resources}{'database'}};
  }
  return;
}

# Returns @list
sub getCustomButtons
{
  my SiteApp $self = shift;
  if (exists($self->{Resources}{'custom_button'})) {
    return @{$self->{Resources}{'custom_button'}};
  }
  return;
}

sub getInstallPrefix
{
  my SiteApp $self = shift;
  my $p = $self->{SiteApp}{'install_prefix'};
  return ($p eq '.') ? '' : $p;
}

# Returns true if site app is installed on domain
sub isDomainSiteapp
{
  my SiteApp $self = shift;
  return 'domain' eq $self->{SiteApp}{'dom_type'};
}

# Returns true if site app is installed on the given subdomain
sub isSubdomainSiteapp( $ )
{
  my SiteApp $self = shift;
  my ($subdom_id) = @_;
  return ('subdomain' eq $self->{SiteApp}{'dom_type'}) && ($subdom_id == $self->{SiteApp}->{'dom_id'});
}

# Returns true if site application is installed into ssl directory
sub isSsl
{
  my SiteApp $self = shift;
  return 'httpsdocs' eq $self->{SiteApp}{'htdocs_directory'};
}

# Returns list of files from htdocs directory, belonging
# to site application. Uses paths relative to htdocs.
# Returns @list
sub getHtdocsFiles
{
  my SiteApp $self = shift;
  return map {$self->{SiteApp}{'install_prefix'} . "/$_"} @{$self->{htdocs}};
}

# Returns list of files from cgi-bin directory, belonging
# to site application. Uses paths relative to cgi-bin.
# Returns @list
sub getCgibinFiles
{
  my SiteApp $self = shift;
  return map {$self->{SiteApp}{'install_prefix'} . "/$_"} @{$self->{cgi_bin}};
}

# Returns error message, indicating erroneous state of the object
sub error
{
  my SiteApp $self = shift;
  return $self->{error};
}

sub getAPSClientItemLicenseType
{
  my SiteApp $self = shift;
  my $ptrRow;

  my $license_type;

  my $sql = "SELECT lt.license_type_hash FROM APSLicenseTypes AS lt INNER JOIN APSApplicationItems AS ai ON (ai.license_type_id = lt.id) INNER JOIN APSClientApplicationItems AS cai ON (cai.app_item_id = ai.id) AND cai.id=?";
  if ( ( $self->{dbh}->execute_rownum($sql, $self->{SiteApp}{'capp_item_id'}) ) && ( $ptrRow = $self->{dbh}->fetchrow() ) ) {
      $license_type = $ptrRow->[0];
  }
  $self->{dbh}->finish();
  return $license_type;
}

sub getSappPackageId
{
  my SiteApp $self = shift;
  return;
}

sub getDnsRecords
{
  my SiteApp $self = shift;
  return;
}

sub _getHtdocsFiles
{
  my SiteApp $self = shift;
  # TODO: The following problem should be addressed:
  # 
  # If site application creates directories for data storage in run-time
  # they are not listed in SiteAppFiles table, and therefore not backuped together
  # with site application. But they also will not be backuped together with hosting
  # content, as site application owns their directory. Hosting content backup
  # does not include files/directories, owned by site application.
  # As a workaround we'll register all files in site app directory as files of the
  # given siteapp (for non / directories)
  # 
  # Proper solution is one of:
  # 1. backup site app content and list of site app files separately
  # 2. include unregistered files from siteapp directory into hosting content backup
  #if ($self->{SiteApp}{'install_prefix'} ne '.') {
    $self->{htdocs} = ['.'];
    return $self->{htdocs};
  #}

  my $sql = "SELECT file FROM SiteAppFiles WHERE instance_id=? AND prefix='htdocs'";
  if ($self->{dbh}->execute_rownum($sql, $self->{id})) {
    while (my $ptrRow = $self->{dbh}->fetchrow()) {
      push @{$self->{htdocs}}, $ptrRow->[0];
    }
  }
  $self->{dbh}->finish();

  return $self->{htdocs};
}

sub _getCgibinFiles
{
  my SiteApp $self = shift;

  my $sql = "SELECT file FROM SiteAppFiles WHERE instance_id=? AND prefix='cgi-bin'";
  if ($self->{dbh}->execute_rownum($sql, $self->{id})) {
    while (my $ptrRow = $self->{dbh}->fetchrow()) {
      push @{$self->{cgi_bin}}, $ptrRow->[0];
    }
  }
  $self->{dbh}->finish();

  return $self->{cgi_bin};
}

sub _sqlError {
  my SiteApp $self = shift;
  my ($message) = @_;
  $self->{error} = $message;
  return;
}

sub _getParams
{
  my SiteApp $self = shift;
  my $sql = "SELECT parameter, value FROM Parameters WHERE id=?";
  if ($self->{dbh}->execute_rownum($sql, ${$self->{SiteApp}}{'params_id'})) {
    while (my $ptrRow = $self->{dbh}->fetchrow()) {
      $ptrRow->[1] ||= ''; #NULL => ''
      $self->{Parameters}{$ptrRow->[0]} = $ptrRow->[1];
    }
  }
  $self->{dbh}->finish();
  return;
}

sub _getLinkedResources
{
  my SiteApp $self = shift;
  my $sql = "SELECT * FROM SiteAppResources WHERE app_id=?";
  if ($self->{dbh}->execute_rownum($sql, $self->{id})) {
    while (my $ptrRow = $self->{dbh}->fetchhash()) {
      push @{$self->{Resources}{$ptrRow->{'type'}}}, {'id' => $ptrRow->{'res_id'}, 'param' => defined $ptrRow->{'res_param_1'} ? $ptrRow->{'res_param_1'} : undef};
    }
  }
  $self->{dbh}->finish();
  return;
}

sub _getPackageSpec
{
  my SiteApp $self = shift;

  my ($sappId, $sql);


  $sql = "SELECT ai.pkg_id FROM APSApplicationItems ai INNER JOIN APSClientApplicationItems cai ON (ai.id = cai.app_item_id) INNER JOIN SiteApps sa ON (sa.capp_item_id = cai.id) AND sa.capp_item_id = ?";
  if ( ( $self->{dbh}->execute_rownum($sql, $self->{SiteApp}->{'capp_item_id'}) ) && ( my $rowPtr = $self->{dbh}->fetchrow() ) ) {
    $sappId = $rowPtr->[0];
  }
  $self->{dbh}->finish();


  $sql = "SELECT * FROM SiteAppPackages WHERE id=?";
  my $hashPtr;
  unless ( ( $self->{dbh}->execute_rownum($sql, $sappId) ) && ( $hashPtr = $self->{dbh}->fetchhash() ) ) {
    $self->{dbh}->finish();
    return $self->_sqlError('Can not find package in the database');    
  }
  $self->{Package} = $hashPtr;
  $self->{dbh}->finish();
  return;
}

1;
