#!/usr/bin/perl
use XML::LibXML;
use XML::LibXML::Common;
use XML::NamespaceSupport;
use XML::SAX;
use IO::Socket;
use Digest::MD5 'md5_hex';


if($ARGV <=1){

#    exit;    exit;
}
my $nntpserver="localhost";
my $nntpport=119;
#my $nntpserver="news.virginmedia.com";
my $getpar2s=0;
my $dummyrun=0;
my $reversefiles=0;
foreach $option (@ARGV){
  if($option eq "-h"){
    print "NZBGet [options] <file.nzb>\n  -s <server> - Specify server\n  -p <port>    - Specify port\n  -p2         - Get PAR2 files\n  -r          - Reverse file order\n";
    exit;
  }
  if(substr($option, 0, 2) eq "-s"){
    #Specified server
    $nntpserver=substr($option, 2);
  }
  if(substr($option, 0, 2) eq "-p"){
    $nntpport=substr($option, 2);
  }
  if($option eq "-p2"){
    $getpar2s=1;
    print "Getting par2 files.\n";
  }
  if($option eq "-r"){
    $reversefiles=1;
  }
}

if(! -d "0"){
  mkdir("0", 0770);print "Making cache folder ./0\n";
}
if(! -d "1"){
  mkdir("1", 0770);print "Making cache folder ./1\n";
}
if(! -d "2"){
  mkdir("2", 0770);print "Making cache folder ./2\n";
}
if(! -d "3"){
  mkdir("3", 0770);print "Making cache folder ./3\n";
}
if(! -d "4"){
  mkdir("4", 0770);print "Making cache folder ./4\n";
}
if(! -d "5"){
  mkdir("5", 0770);print "Making cache folder ./5\n";
}
if(! -d "6"){
  mkdir("6", 0770);print "Making cache folder ./6\n";
}
if(! -d "7"){
  mkdir("7", 0770);print "Making cache folder ./7\n";
}
if(! -d "8"){
  mkdir("8", 0770);print "Making cache folder ./8\n";
}
if(! -d "9"){
  mkdir("9", 0770);print "Making cache folder ./9\n";
}
if(! -d "a"){
  mkdir("a", 0770);print "Making cache folder ./a\n";
}
if(! -d "b"){
  mkdir("b", 0770);print "Making cache folder ./b\n";
}
if(! -d "c"){
  mkdir("c", 0770);print "Making cache folder ./c\n";
}
if(! -d "d"){
  mkdir("d", 0770);print "Making cache folder ./d\n";
}
if(! -d "e"){
  mkdir("e", 0770);print "Making cache folder ./e\n";
}
if(! -d "f"){
  mkdir("f", 0770);print "Making cache folder ./f\n";
}


#my $nntpsock = new IO::Socket::INET (PeerAddr => 'news.virginmedia.com', PeerPort => '119', Proto => 'tcp');
my $nntpsock;
connectionInit();

foreach $option (@ARGV){
  if(substr($option, 0, 1) ne "-"){
    processNZB($option);
  }
}

close($nntpsock);
exit 0;

sub processNZB{
  my($filename)=@_;
  my $parser = XML::LibXML->new();
  my $doc = $parser->parse_file($filename);
  $filesystem = $doc->getDocumentElement();
  @nodes=$filesystem->childNodes;


  #binmode($nntpsock);
  if($reversefiles){
    @nodes=reverse(@nodes)
  }
  foreach $node (@nodes) {
    if($node->nodeName eq "file"){
      getFile($node, $nntpsock, $filename);
    }
  }
}

sub getFile{
    mkdir("out");
    my($node, $nntpsock, $filename)=@_; #The node is the file.
    $subject = $node->getAttribute("subject"); #Temporary subject.
    print $subject."\n";
    if($getpar2s == ($subject !~ m/\.PAR2/i)){
      print "Skipping par2\n";
      return;
    }
    $segmentsnode=$node->getChildrenByTagName("segments")->item(0);
    @segments=$segmentsnode->getChildrenByTagName("segment");
    if($reversefiles){
      @segments=reverse(@segments);
    }

    foreach $segment (@segments){
      #print $segment->getAttribute("bytes")." ".$segment->textContent."\n";
      print "Getting ".$segment->textContent." ";
      if(getSegment($segment->textContent, $filename)==2){
        #die "Failed\n";
        connectionInit();
        getSegment($segment->textContent, $filename);
      }
    }
 
 
 
}

sub getSegment{
  my($segment, $filename)=@_;

  my $cachefile=md5_hex $segment;
  $cachefile=chop($cachefile)."/".$segment;
  if(-e $cachefile){
    print "Already have.\n";
    return(0);
  }

  print $nntpsock "BODY <".$segment.">\r\n";
  $response=0;

  my @data;
  while(substr($response, 0, 3) eq 0){
    $response=<$nntpsock>;
  }

  binmode($nntpsock);

  if(substr($response, 0, 3) eq 222){
    $lines=0;
    binmode(OUTFILE);
    binmode($nntpsock);
    $buffer=<$nntpsock>;
    while($buffer ne ".\r\n"){
      if(substr($buffer, 0, 2) eq ".."){
        $buffer=substr($buffer, 1);
      }
      if($buffer ne "\r\n"){
        push(@data, $buffer);
      }
      $buffer=<$nntpsock>;
      if(not $buffer){
        print "instnzb failed: connection lost.\n";
        return(2); #Failed, and in such a way that the connection needs to be redone.
      }
      $lines++;
    }
    $buffer="";
    print $lines." lines.\n";
  }
  else{
    print "instnzb failed: ".$response."\n";
    return(1); #Failed, but not seriously - try the next part as normal.
  }

  open(OUTFILE, ">$cachefile");
  print OUTFILE @data;
  close(OUTFILE);

  return 0; #A value of zero means success, 
}

sub connectionInit{
  print "Connecting to $nntpserver:$nntpport\n";
  $nntpsock = new IO::Socket::INET (PeerAddr => $nntpserver, PeerPort => $nntpport, Proto => 'tcp', Timeout => '5');
  if(! $nntpsock){
    print "Connnection failed.\n";
    die;
  }
  print <$nntpsock> . "\n";
  print $nntpsock "MODE READER\r\n"; #Not sure what this does, but I think it might be important somehow.
  print <$nntpsock> . "\n";
}
