package Ernad::Email;

use strict;
use warnings;

use Data::Dumper;
use Encode;
use File::Basename;
use File::Slurp;
use File::Path;
use File::Temp qw/ tempfile tempdir /;

## form issue nucleus
sub prepare_email {
  my $doc=shift;
  my $sheet_name=shift // '';
  my $save_email=shift // '';
  my $verbose=shift // '';
  $verbose=0;
  my $e=$main::e or die 'no erimp';
  ## check input
  my $ref_xml=ref($doc);
  if(not $ref_xml eq 'XML::LibXML::Document') {
    die "send_mail argument is $ref_xml, not a document.";
  }  
  if(not $e) {
    $e=$Erimp::e // $main::e;
  }
  if(not ref($e) eq 'Ernad::Erimp') {
    die "I can't see the erimp.";
  }
  my $headers=&form_headers($doc,$e,$sheet_name);
  my $top = MIME::Entity->build(%$headers);
  ## create attachments
  my $sheet_dir=$e->{'dir'}->{'style'};
  my $sheet_name_end="_$sheet_name".$e->{'const'}->{'xsl_ext'};
  my $sheet_file;
  ## save file is a path/file expression
  if($save_email) {
    my $save_email_dir=dirname($save_email);
    if(not -d $save_email_dir) {
      mkpath($save_email_dir);
    }
  }
  ## text first
  $sheet_file="$sheet_dir/email_text".$sheet_name_end;
  if(-f $sheet_file) {
    my $text=&form_body($doc,$e,$sheet_name,'text');
    my $save_file=$save_email.'.txt';
    write_file($save_file,$text);
    $top->attach( Type => 'text/plain',
                  Charset => 'utf-8',
                  Data => $text,
                  Encoding => '8BIT' );
  }
  ## html 
  $sheet_file="$sheet_dir/email_html".$sheet_name_end;
  if(-f $sheet_file) {
    my $html=&form_body($doc,$e,$sheet_name,'html');
    my $save_file=$save_email.'.html';
    write_file($save_file,$html);
    $top->attach( Type => 'text/html',
                  Charset => 'utf-8',
                  Data => $html->toString(),
                  Encoding => '8BIT' );
  }
  ## general save_file
  my $save_file;
  my $save_fh;
  if($save_email) {
    $save_file=$save_email.'.mail';
  }
  else {
    ($save_fh, $save_file) = tempfile(DIR => '/tmp');  
  }
  write_file($save_file,$top->stringify) or die;
  if($verbose) {
    print "wrote $save_file\n";
  }
  return $save_file;
}

sub send_email {
  my $mail_file=shift // '';
  my $do_delete=shift // '';
  if(not $mail_file) {
    die "no email file to send";
  }
  if(not -f $mail_file) {
    die "no such file: '$mail_file'";
  }
  my $e=$main::e or die 'no erimp';
  ## sending it out
  my $exim_path=$e->{'conf'}->{'exim_path'};
  my $cmd = "cat $mail_file | $exim_path -t";
  system($cmd);
  ## remove the temporary file, keep the saved file
  if($mail_file=~m|^/tmp/| or $do_delete) {
    unlink $mail_file;
  }
}

sub form_headers {
  my $doc=shift;
  my $e=shift // '';
  my $sheet_name=shift // '';
  my $sheet="headers_$sheet_name";
  my $headers_doc=$e->transform($doc,$sheet) or die;
  my $headers_xp="/e:headers/e:header";
  my $xpc=$e->{'xpc'};
  my @headers=$xpc->findnodes($headers_xp,$headers_doc)->get_nodelist();
  my $h;
  foreach my $header (@headers) {
    #print $header->toString;
    my $value=$header->getAttribute('value') or next;
    my $name=$header->getAttribute('name');
    ## several headers with the same name are not supported! 
    $h->{$name}=&email_header_encode($value);
  }
  #print Dumper $h;
  return $h;
}

sub form_body {
  my $doc=shift;
  my $e=shift // '';
  my $sheet_name=shift // '';
  my $type=shift;
  my $sheet="email_$type"."_$sheet_name";
  my $output;
  if($type eq 'text') {
    $output=$e->transform_to_text($doc,$sheet) or die;
  }
  else {
    $output=$e->transform($doc,$sheet) or die;
  }
  return $output;
}

## http://stackoverflow.com/questions/11969775/how-to-encode-mail-subject-in-perl
sub email_header_encode {
  my $string=shift;
  if($string!~/[^\x00-\x7F]/) {
    return $string;
  }
  ## try separate out the email address
  if($string=~m|^(.*)\s+(<[^@]+@[^@]+>)$|) {
    my $name=$1;
    my $mad=$2;
    my $name_encoded=encode('MIME-Header', $name);
    return "$name_encoded $mad";
  }
  ## fallback case
  return encode('MIME-Header', $string);
}

1;
