#!/usr/bin/perl

use strict;
use warnings;
use URI;
use Compress::Zlib;
use HTTP::Status;
use HTTP::Message;
use HTTP::Request;
use LWP::UserAgent;

my $uuid = '3d32b20481b1df262ada6899540c8701';

my $uri = 'http://mobile.maps.yandex.net/printer?uuid=' . $uuid . '&protocol_ver=2&lang=ru-RU&';

my $ua = LWP::UserAgent->new (
   agent => 'YandexMaps/1003 CFNetwork/609.1.4 Darwin/13.0.0',
   keep_alive  => 1
);

sub ym_add_field_to_request
{
  my $req = shift;
  my $field_name = shift;
  my $field_value = shift;
  my $msg = HTTP::Message->new(['Content-Disposition' => 'form-data; name="' . $field_name . '"']);
  $msg->add_content($field_value);
  $req->add_part($msg);
}

sub ym_add_content_to_request
{
  my $req = shift;
  my $field_name = shift;
  my $field_content_type = shift;
  my $field_content = shift;
  my $msg = HTTP::Message->new(
    [
      'Content-Disposition' => 'form-data; name="' . $field_name . '"',
      'Content-Type' => $field_content_type
    ]
  );
  $msg->add_content($field_content);
  $req->add_part($msg);
}

sub ym_get_boundary
{
  my $boundary = '--------------';
  my @rand = ('0'..'9');    
  for (0..25){$boundary .= $rand[rand(@rand)];}
  return $boundary;
}

sub mycrc32
{
  my ($input, $init_value, $polynomial) = @_;

  $init_value = 0 unless (defined $init_value);
  $polynomial = 0xedb88320 unless (defined $polynomial);

  my @lookup_table;

  for (my $i=0; $i<256; $i++) {
    my $x = $i;
    for (my $j=0; $j<8; $j++) {
      if ($x & 1) {
        $x = ($x >> 1) ^ $polynomial;
      } else {
        $x = $x >> 1;
      }
    }
    push @lookup_table, $x;
  }

  my $crc = $init_value ^ 0xffffffff;

  foreach my $x (unpack ('C*', $input)) {
    $crc = (($crc >> 8) & 0xffffff) ^ $lookup_table[ ($crc ^ $x) & 0xff ];
  }

  $crc = $crc ^ 0xffffffff;

  return $crc;
}

sub ym_get_crc
{
  my $src_str = shift;
  my $key_str = shift;
  
  my @data = unpack("C*", $src_str);
  my @key = unpack("C*", $key_str);
  
  my $data_size = @data;
  my $key_size = @key;
  
  for (my ($i) = 0; $i < $data_size; $i++) {
    $data[$i] ^= $key[$i % $key_size];     
  }
  
  return mycrc32(pack("C*", @data));
}

sub sas_main
{
  my $x = shift;
  my $y = shift;
  my $z = shift;
  
  $z--;
  
  my $tiles_xml = '<?xml version="1.0" ?><tiles><tile x="' . $x . '" y="' . $y . '" zoom="' . $z . '" layer="map" size="1" /></tiles>';
  my $tiles_gzip = Compress::Zlib::memGzip($tiles_xml);
  my $packet_id = ym_get_crc($tiles_gzip, $uuid);
  
  my $request = HTTP::Request->new('POST', $uri);
  
  $request->header('Content-Type' => 'multipart/form-data; boundary=' . ym_get_boundary() );
  $request->header('Accept' => '*/*');
  $request->header('Accept-Encoding' => 'gzip');
  $request->header('Accept-Language' => 'ru');
  $request->header('Lang' => 'ru-RU');
  
  ym_add_field_to_request($request, 'scalefactor', '2');
  ym_add_field_to_request($request, 'protocol_ver', '2');
  ym_add_field_to_request($request, 'gzip', '1');
  ym_add_field_to_request($request, 'packetid', $packet_id);
  ym_add_field_to_request($request, 'uuid', $uuid);
  ym_add_content_to_request($request, 'tiles', 'application/gzip', $tiles_gzip);
  
  my $response = $ua->request($request);
  
  if ($response->is_success)
  {
    my @data = unpack("C*", $response->content);
    my @ytld = splice(@data, 0, 0x34);
    
    my $img_size = $response->content_length - 52;
    my $img = pack("C*", @data);
    
    my $content_type = 'image/png';
    my $old_content_type = ($response->content_type);
    my $old_size = ($response->content_length);
    
    my $http_header = ($response->headers_as_string);
    
    $http_header =~ s/$old_content_type/$content_type/i;
    $http_header =~ s/$old_size/$img_size/i;
    
    my @ret = ();
    push @ret, ($response->code);
    push @ret, ($img_size);
    push @ret, ($content_type);
    push @ret, ($http_header);
    push @ret, ($img);
    
    return \@ret;
    
    #### return ($response->code);
  }
  else
  {
    return ($response->code);
  }
}
