#
# (c) Jan Gehring <jan.gehring@gmail.com>
# 
# vim: set ts=3 sw=3 tw=0:
# vim: set expandtab:
   
package Rex::Interface::Connection::HTTP;
   
use strict;
use warnings;

use Rex::Interface::Connection::Base;
use LWP::UserAgent;
use JSON::XS;
use Data::Dumper;
use Rex::Cache;

use base qw(Rex::Interface::Connection::Base);

sub new {
   my $that = shift;
   my $proto = ref($that) || $that;
   my $self = $that->SUPER::new(@_);

   bless($self, $proto);

   # activate caching
   $Rex::Cache::USE = 1;

   return $self;
}

sub error { };
sub connect {
   my ($self, %option) = @_;
   my ($user, $pass, $server, $port, $timeout);

   $user    = $option{user};
   $pass    = $option{password};
   $server  = $option{server};
   $port    = $self->_get_port($option{port});
   $timeout = $option{timeout};

   $self->{server} = $server;
   $self->{port} = $port;

   if($server =~ m/([^:]+):(\d+)/) {
      $server = $self->{server} = $1;
      $port   = $self->{port}   = $2;
   }

   $self->{__user} = $user;
   $self->{__pass} = $pass;

   if( ! Rex::Config->has_user && Rex::Config->get_ssh_config_username(server => $server) ) {
      $user = Rex::Config->get_ssh_config_username(server => $server);
   }

   $self->ua->credentials(
      "$server:$port",
      "Rex::Endpoint::HTTP",
      $user => $pass,
   );

   my $resp = $self->post("/login");
   if($resp->{ok}) {
      Rex::Logger::info("Connected to $server, trying to authenticate.");
   }
   else {
      Rex::Logger::info("Can't connect to $server", "warn");
      $self->{connected} = 0;
      return;
   }

   Rex::Logger::info("Connecting to $server:$port (" . $user . ")");

}

sub disconnect { };
sub get_connection_object { my ($self) = @_; return $self; };
sub get_fs_connection_object { my ($self) = @_; return $self; };
sub is_connected { return 1; };
sub is_authenticated { return 1; };

sub exec {
   my ($self, $cmd) = @_;
}

sub ua { 
   my ($self) = @_;
   return $self->{ua} if $self->{ua};

   $self->{ua} = LWP::UserAgent->new;
}

sub upload {
   my ($self, $data) = @_;

   my $res = $self->ua->post($self->_get_proto . "://" . $self->{server} . ":" . $self->{port} . "/fs/upload",
               Content_Type => "multipart/form-data",
               Content => $data);

   if($res->is_success) {
      return decode_json($res->decoded_content);
   }
   else {
      die("Error requesting /fs/upload.");
   }
}

sub post {
   my ($self, $service, $data, $header) = @_;

   $header ||= {};
   $data ||= {};

   if(! ref($data)) {
      die("Invalid 2nd argument. must be arrayRef or hashRef!\npost(\$service, \$ref)");
   }

   my $res = $self->ua->post($self->_get_proto . "://" . $self->{server} . ":" . $self->{port} . "$service", %{$header}, Content => encode_json($data));

   if($res->is_success) {
      return decode_json($res->decoded_content);
   }
   else {
      die("Error requesting $service.\n\nError: " . $res->{_content});
   }

}

sub get {
   my ($self, $service) = @_;

   my $res = $self->ua->get($self->_get_proto . "://" . $self->{server} . ":" . $self->{port} . "$service");

   if($res->is_success) {
      return decode_json($res->decoded_content);
   }
   else {
      die("Error requesting $service.");
   }

}

sub get_connection_type { return "HTTP"; }

sub _get_proto {
   return "http";
}

sub _get_port {
   my ($self, $port) = @_;
   return $port || 8080;
}

1;
