package PDBAtom;


use lib qw(Core ./);
use String;

sub new {
   my ($class) = @_;
   my $self = {
	_name => '',
	_x => '',
	_y => '',
	_z => '',
	_line => undef

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

sub parseLine {
    my ($self, $line) = @_;
    $self->{_name} = trim(substr($line, 12, 4));
    $self->{_x} = trim(substr($line, 30, 8));
    $self->{_y} = trim(substr($line, 38, 8));
    $self->{_z} = trim(substr($line, 46, 8));
    chomp $line;
    my ($flag, $reformat_line) = $self->reformat_ATOM_line($line); # delete chain indetifier
    if ($flag == 1) {
	$self->{_line} = $reformat_line;
    } else {
	$self->{_line} = $line."\n";
    }
}


sub reformat_ATOM_line {
  my ($line, $fKeep_chain) = @_;
  chomp $line; # remove "\n"
  # $line = uc($line); # to Upper Case
  while(length($line) < 80){
        $line .= " "; # add " " to make the line of full length (80 positions)
  }
  my $atom_num = substr($line, 6, 5);
    $atom_num =~ s/\s+//g; # remove spaces
  my $blank1 = substr($line, 11, 1);
  my $atom_name = uc(substr($line, 12, 4));
    $atom_name =~ s/\s+//g;
  my $alt_loc = substr($line, 16, 1);
  my $res_name = uc(substr($line, 17, 3));
  my $blank2 = substr($line, 20, 1);
  my $chain_id = substr($line, 21, 1);
  my $res_num = substr($line, 22, 4);
    $res_num =~ s/\s+//g; # remove spaces 
  my $ins_code = substr($line, 26, 1);
  my $blank3 = substr($line, 27, 3);
  my $x = substr($line, 30, 8);
    $x =~ s/\s+//g;
    #$x = sprintf("%f8.3", $x);
  my $y = substr($line, 38, 8);
    $y =~ s/\s+//g;
    #$y = sprintf("%f8.3", $y);
  my $z = substr($line, 46, 8);
    $z =~ s/\s+//g;
    #$z = sprintf("%f8.3", $x);
  my $occ = substr($line, 54, 6);
    $occ =~ s/\s+//g;
    #if("" eq $occ) { $occ = 0.00;}
  my $t_f = substr($line, 60, 6);
    $t_f =~ s/\s+//g;
    #if("" eq $t_f) { $t_f = 0.00;}
  my $blank4 = substr($line, 66, 10);
  my $elem = uc(substr($line, 76, 2));
    $elem =~ s/\s+//g;
    #if("" eq $elem){$elem = "  ";}
  my $charge = uc(substr($line, 78, 2));
    $charge =~ s/\s+//g;
    #if("" eq $charge){ $charge = "  ";}

  #check $atom_num
  if($atom_num =~ m/[0-9]{1,5}/){
     # $atom_num = sprintf("%5d", $atom_num);
  } else {
      return 0, "Bad format atom_num[7-11] in $line\n"; # 
  }
  #check $atom_name
  if($atom_name =~ m/^[0-9]{0,1}H[A-Z0-9]{0,}$/){
     return 0, " Hydrogens are skipped \n";
  } elsif ($atom_name =~ m/^[A-Z0-9]{1,3}$/){
     $atom_name = sprintf(" %-3s", $atom_name); #left-justified
  } elsif ($atom_name =~ m/^[A-Z0-9]{4,4}$/){
     # do nothing - it matches the format
  } else {
    return 0, "Bad  format of atom_name[13-16] in $line\n";
  }
  #check alt_loc # if 
  my $flag_alt_loc = 0;
  if($alt_loc =~ m/^\S$/){
     $flag_alt_loc = 1; # flag to handle with alternate locations
  }
  $alt_loc = " "; # delete alt_loc
  #check res_name
  if(!defined($AMINOACIDS_ATOMS{$res_name})){
    return 0, "Bad format of res_name[18-20] in $line\n";
  }
  #check chain_id delete chain_id in CASP predictions
  if($fKeep_chain = undef || $fKeep_chain == 0 ){
     $chain_id = " ";
  }
  #check res_num
  if($res_num =~ m/^[0-9]{1,4}$/){
    # $res_num = sprintf("%4d", $res_num);
  }else{
     return 0, "Bad format of res_num[23-26] in $line\n";
  }
  # check insertion code
  # in CASP ins_code has to be " "
  if($ins_code =~ m/\S+/){
    return 0, "Bad format of ins_code[27] in $line\n";
  }else{
    $ins_code = " ";
  }
  #check coordinates
  if($x =~ m/^-{0,1}[0-9]{1,}\.[0-9]{1,3}$/){
    # $x = sprintf("%8.3f", $x);
  }else{
    return 0, "Bad format of x_coord[31-38] in $line\n";
  }
  if($y =~ m/^-{0,1}[0-9]{1,}\.[0-9]{1,3}$/){
    # $y = sprintf("%8.3f", $y);
  }else{
    return 0, "Bad format of y_coord[39-46] in $line\n";
  }
  if($z =~ m/^-{0,1}[0-9]{1,}\.[0-9]{1,3}$/){
    # $z = sprintf("%8.3f", $z);
  }else{
    return 0, "Bad format of z_coord[47-54] in $line\n";
  }
  #check occupancy
  if("" eq $occ) { $occ = "1.00";}
  if($occ =~ m/^[0-9]{1,}\.[0-9]{1,2}$/){
     $occ = sprintf("%6.2f",$occ);
  }else{
     $occ = "1.00";
     # return 0, "Bad format of occ[55-60] in $line\n";
  }
  #check temperature factor
  if("" eq $t_f) { $t_f = "0.00";}
  if($t_f =~ m/^[0-9]{1,}\.[0-9]{1,2}$/){
     $t_f = sprintf("%6.2f",$t_f);
  }else{
      $t_f = "0.00";
     #return 0, "Bad format of temperature_factor[61-66] in $line\n";
  }
  #check $elem
  if("" eq $elem){
    $elem = "  ";
  }elsif($elem =~ m/^[A-Z]{1,2}$/){
    $elem = sprintf("%2s", $elem);
  }else{
    #return 0, "Bad format of element[77-78] in $line \n";
    $elem = sprintf("%2s", substr($atom_name, 0, 1));
  }
  #check $charge delete it in CASP predictions
  $charge = "  ";
  my $result = sprintf("ATOM  %5d %4s%1s%3s %1s%4d%1s   %8.3f%8.3f%8.3f%6.2f%6.2f          %2s%2s\n", $atom_num, $atom_name, $alt_loc, $res_name, $chain_id, $res_num, $ins_code, $x, $y, $z, $occ, $t_f, $elem, $charge);
  return (1, $result, $flag_alt_loc);
}


1;
