<?php
/* Demonstration of available options on the qrCode() command */
// require __DIR__ . '/../autoload.php';
require 'api/Mike42/autoload.php';

use Mike42\Escpos\Printer;

class NfcCodePrint extends Printer{
  private $p_chars_line = 64;
  private $p_xml_string = '';

  // métodos mágicos get e set
  public function __set($atrib, $value){
    $this->$atrib = $value;
  }

  public function __get($atrib){
    return $this->$atrib;
  }

  // faz a montagem para o cupom
  function montarCupom($p_string){
    $xml = simplexml_load_string($p_string);

    $this->setCenterText($xml->infCFe->emit->xFant);
    $this->setCenterText($xml->infCFe->emit->xNome);
    $this->setCenterText($xml->infCFe->emit->enderEmit->xLgr . "," . $xml->infCFe->emit->enderEmit->nro);
    $this->setCenterText($xml->infCFe->emit->enderEmit->xMun . " - SP");

    $this->info_emissor = 'CNPJ ' . $xml->infCFe->emit->CNPJ . ' IE ' . $xml->infCFe->emit->IE . ' IM ' . $xml->infCFe->emit->IM;
    $this->setCenterText($this->info_emissor);
    $this->setLinhaTracejada();

    // $ds_extrato_venda = 'Extrato Nro. { á definir}' . $this->nr_extrato_venda;
    $this->nr_cupom_venda = $xml->infCFe->ide->nCFe;
    $this->ds_extrato_venda = 'Extrato Nro.' . $this->nr_cupom_venda;
    $this->setCenterTextBold($this->ds_extrato_venda, 1, 1);
    $this->setCenterTextBold("CUPOM FISCAL ELETRÔNICO - SAT", 1, 2);
    $this->setLinhaTracejada();

    $this->ds_dest_doc = $xml->infCFe->dest->CPF . $xml->infCFe->dest->CNPJ;
    $this->ds_dest_nome= $xml->infCFe->dest->xNome;
    $this->setLeftText("CPF/CNPJ do Consumidor: " . $this->ds_dest_doc);
    $this->setLeftText("Nome / Razão Social: " . $this->ds_dest_nome );
    $this->setLinhaTracejada();

    // acrescenta cada produto a um array
    $array_produtos=array();
    for ($i=0; $i < count($xml->infCFe->det); $i++) {
      $item = (array)$xml->infCFe->det[$i];
      array_push($array_produtos, $item);
    }

    // acrescenta cada meio de pagamento a 1 Array
    $array_pagto = array();
    for ($i=0; $i < count($xml->infCFe->pgto->MP); $i++) {
      $item = (array)$xml->infCFe->pgto->MP[$i];
      array_push($array_pagto, $item);
    }

    $array_itens_prod = $array_produtos;

    $this->ds_titulo_itens = '# | COD | DESC | QTD | UN | VL UN R$ |VL ITEM R$';
    $this->setLeftText($this->ds_titulo_itens);
    $this->setLinhaTracejada();

    // foreach ($array_itens_prod as $key => $array_item) {
    for ($i=0; $i < count($array_itens_prod) ; $i++) {
      $p_item = (array)$array_itens_prod[$i]['prod'];

      // dados do produto
      $nr_item = $i +1;
      $ds_info_produto  = substr("000$nr_item", -3);
      $ds_info_produto .= " " . substr("00000000000000" . $p_item['cProd'], -14);
      $ds_info_produto .= " " . $p_item['xProd'] . " ";

      // dados da venda do item
      $ds_item_valores  = " " . $p_item['qCom'];
      $ds_item_valores .= " " . $p_item['uCom'];
      $ds_item_valores .= " X ". $p_item['vUnCom'];
      $ds_item_valores .= " " . $p_item['vProd'];

      // se tamanho da linha maior de $p_chars_line 64 caracteres, quebra linha
      if(strlen($ds_info_produto . $ds_item_valores)>$this->p_chars_line){
        $this->setLeftText(substr($ds_info_produto, 0, $this->p_chars_line));
        $this->setRigthText($ds_item_valores);
      }else{
        $linha_item = $this->setStringCharsLine($ds_info_produto, $ds_item_valores);
        $this->setCenterText($linha_item);
      }

      // destaca o desconto do item
      if(isset($p_item['vDesc'])){
        if($p_item['vDesc']!='0.00'){
          $this->setRigthText('-Desconto sobre Item R$ ' . $p_item['vDesc']);
        }
      }
    }

    $this->vl_total_cfe = $xml->infCFe->total->vCFe;
    $linha_total = $this->setStringCharsLine("TOTAL R$ ", $this->vl_total_cfe);
    $this->setCenterTextBold($linha_total, 1, 2 );
    $this->vl_troco = floatval($this->vl_total_cfe);

    // se houve mais de uma forma de pagamento, faz loop
    foreach ($array_pagto as $key => $value) {
        $cd_forma_pgto = $value['cMP'];
        $vl_pago_forma = $value['vMP'];
        $ds_forma_pgto = $this->getDescricaoMP( $cd_forma_pgto);
        $linha_pgto = $this->setStringCharsLine($ds_forma_pgto, $vl_pago_forma);
        $this->setCenterText($linha_pgto, 1, 1 );
        $this->vl_troco -= $vl_pago_forma;
      }

      $this->vl_troco = number_format($this->vl_troco, 2, ',', ' ');

      $linha_troco = $this->setStringCharsLine("Troco R$ ", $this->vl_troco);
      $this->setCenterText($linha_troco);
      $this->setLinhaTracejada();

      $this->setCenterTextBold("OBSERVAÇÕES DO CONTRIBUINTE", 1, 1);

      $originalDate= $xml->infCFe->ide->dEmi . " " . $xml->infCFe->ide->hEmi;
      $dt_hora_completa= date("d-m-Y H:i:s", strtotime($originalDate));
      $this->ts_cfe = $dt_hora_completa;

      $this->cd_loja = '0001';
      $this->nr_caixa= $xml->infCFe->ide->numeroCaixa;

      $this->ds_emissor_obs = "DataMov: " . date("d-m-Y", strtotime($this->ts_cfe)) . " Loja: " . substr("0000" . $this->cd_loja, -4) . " Terminal: " . $this->nr_caixa . " N.Cupom : " . $this->nr_cupom_venda;
      $this->setCenterText($this->ds_emissor_obs);
      $this->setLinhaTracejada();

      $this->ds_info_adic = $xml->infCFe->infAdic->infCpl;
      $this->setLeftText($this->ds_info_adic);

      $this->setCenterTextBold("SAT No." . $xml->infCFe->ide->nserieSAT, 1, 1);

      $this->setCenterText($this->ts_cfe);
      // $this->setCenterTextBold($this->ds_chave, 1, 1);

      $this->ds_chave = $xml->infCFe['Id'];
      $this->setCodigoBarras();
      // qr_code do cupom fiscal
      // estrutura chaveConsulta|timeStamp|valorTotal|CPFCNPJValue|assinaturaQRCODE
      // echo "<br>visualizando a chave:" . $this->ds_chave;
      $this->ds_qrcode = $xml->infCFe->ide->assinaturaQRCODE;

      $qrcodeDate  = $xml->infCFe->ide->dEmi . $xml->infCFe->ide->hEmi;
      // $qrcodeVlCfe = preg_replace("/[^0-9]/", "", $this->vl_total_cfe);

      $p_qr_code = $this->ds_chave . "|" . $qrcodeDate . "|" . $this->vl_total_cfe . "|" . $this->ds_dest_doc . "|" . $this->ds_qrcode;
      $this->setQrCode($p_qr_code);

      // rodapé do Cfe, informações de Versão do SW
      $this->setLinhaTracejada();
      $info_loja = "PDV:" . $this->nr_caixa .
                   " LJ:" . substr("0000" . $this->cd_loja, -4) .
                   " COO:" . $this->nr_cupom_venda .
                   " Operador:" . $this->id_operador . " " . $this->ds_nome_operador;
      $info_loja = $this->setStringCharsLine($info_loja,"");
      $this->setLeftText($info_loja);
      $this->setLeftText($this->ds_versao_sw);
  }

  // retorna o objecto como texto
  public function toString(){
    $st_ret = $this->printer->getPrintBuffer();
    return $st_ret;
  }

  // imprime diretamente para impressora
  public function imprimir(){
    global $caminho;
    
	try {
    // $this->montarCupom();
    $this->cut();
    $this->close();
	} catch (Exception $e) {
		$msg_erro = "Couldn't print to this printer: " . $caminho . " - " . $e -> getMessage() . "\n";
		// addError($msg_erro);
		echo $msg_erro;
	}

    return true;
  }

  function setInformacaoSW($p_id_operador, $p_nm_operador, $p_sw_code){
    $this->id_operador     = $p_id_operador;
    $this->ds_nome_operador= $p_nm_operador;
    $this->ds_versao_sw    = $p_sw_code;
  }

  function getDescricaoMP($cd_mp){
    $ds_ret = 'Dinheiro';
    switch ($cd_mp) {
        case '01':
            $ds_ret = 'Dinheiro';
            break;
        case '02':
            $ds_ret = 'Cheque';
            break;
        case '03':
            $ds_ret = 'Cartão de Crédito';
            break;
        case '04':
            $ds_ret = 'Cartão de Débito';
            break;
        case '05':
            $ds_ret = 'Crédito Loja';
            break;
        case '10':
            $ds_ret = 'Vale Alimentação';
            break;
        case '11':
            $ds_ret = 'Vale Refeição';
            break;
        case '12':
            $ds_ret = 'Vale Presente';
            break;
        case '13':
            $ds_ret = 'Vale Combustível';
            break;
        case '99':
            $ds_ret = 'Vale Combustível';
            break;
        }
    return $ds_ret;
  }

  // linha tracejada para divisão de sessões
  function setLinhaTracejada(){
    $texto = "-";
    $ds_print = str_pad($texto, $this->p_chars_line, "-");
    $this->setLeftText($ds_print);
  }

  // acrescenta espacos para justificar o texto
  function setStringCharsLine($texto1, $texto2){
    $nr_char = $this->p_chars_line - strlen($texto2);

    $ds_ret = str_pad($texto1, $nr_char);
    $ds_ret.= $texto2;
    return $ds_ret;
  }

  function setCodigoBarras(){
    $chave_clear = substr($this->ds_chave, -44);

    $this->setEmphasis(false);

    // $content = "{C" . chr(21) . chr(32) . chr(43);
    $content1 = "{B" . substr($chave_clear, 0, 22);
    $content2 = "{B" . substr($chave_clear, -22);

    $this->setEmphasis(true);
    $this->setBarcodeHeight(64);

    $this->setJustification(1);
    $this-> text("\n$chave_clear\n");

    $this->setBarcodeWidth(2);
    $this->barcode($content1, Printer::BARCODE_CODE128);
    $this->feed();
    $this->barcode($content2, Printer::BARCODE_CODE128);

    $this->selectPrintMode(Printer::MODE_DOUBLE_HEIGHT | Printer::MODE_DOUBLE_WIDTH);
    // $printer->barcode($content, Printer::BARCODE_CODE128);

    /*
    $widths = array(1, 2, 3, 4, 5, 6, 7, 8);
    foreach($widths as $width) {
        $printer -> text("\nWidth $width\n");
        $printer->setBarcodeWidth($width);
        $printer->barcode($content, Printer::BARCODE_CODE128);
    }*/
    $this->feed();
  }

  /* formata uma string para código de barras
  function setStringBarra($p_string){
    $p_return = '';
    for ($i=0; $i <= strlen($p_string); $i += 2) {
      $p_numero = substr($p_string, $i, 2);
      $p_convert= chr($p_numero);

      echo "<br>$p_numero|$p_convert";

      $p_return.= $p_convert;
    }
    return $p_return;
  }*/

  function setQrCode($p_qr_code){
    $this-> setJustification(1);
    $this-> qrCode($p_qr_code, Printer::QR_MODEL_2);
    // $printer -> text("Most simple example\n");
    $this-> feed();
  }

  function setLeftText($value){
    // echo "<br>" . $value;
    $this->setJustification(0);
    // $printer -> qrCode($testStr);
    $this-> setFont(2);
    $this-> selectPrintMode(1);
    $this-> setTextSize( 1, 1);
    $this-> text($value);
    $this-> setJustification();
    $this-> feed();
  }

  function setRigthText($value){
    // echo "<br>" . $value;
    $this->setJustification(2);
    // $printer -> qrCode($testStr);
    $this-> setFont(2);
    $this-> selectPrintMode(1);
    $this-> setTextSize( 1, 1);
    $this-> text($value);
    $this-> setJustification();
    $this-> feed();
  }

  function setCenterText($value){
    // echo "<br>" . $value;

    $this->setJustification(1);
    $this->selectPrintMode(1);
    // $printer -> qrCode($testStr);
    $this -> setFont(2);
    $this -> setTextSize( 1, 1);
    $this -> text($value);
    $this -> setJustification();
    $this -> feed();
  }

  function setCenterTextBold($value, $p_width, $p_heigth){
    // echo "<br>" . $value;

    $this -> setJustification(1);
    $this -> selectPrintMode(40);
    // $printer -> qrCode($testStr);
    $this -> setFont(1);
    $this -> setEmphasis(true);
    $this -> setTextSize($p_width, $p_heigth);
    $this -> text($value);
    $this -> setJustification();
    $this -> feed();
  }

  function title(Printer $printer, $str){
      $printer -> selectPrintMode(Printer::MODE_DOUBLE_HEIGHT | Printer::MODE_DOUBLE_WIDTH);
      $printer -> text($str);
      $printer -> selectPrintMode();
  }
}



/*

// Most simple example
// title($printer, "QR code demo\n");

/* $testStr = "Testing 123";
$printer -> qrCode($testStr);
$printer -> text("Most simple example\n");
$printer -> feed();

// Demo of numeric data being packed more densly
title($printer, "Data encoding\n");
$test = array(
    "Numeric"      => "0123456789012345678901234567890123456789",
    "Alphanumeric" => "abcdefghijklmnopqrstuvwxyzabcdefghijklmn",
    "Binary"       => str_repeat("\0", 40));
foreach ($test as $type => $data) {
    $printer -> qrCode($data);
    $printer -> text("$type\n");
    $printer -> feed();
}

// Demo of error correction
title($printer, "Error correction\n");
$ec = array(
    Printer::QR_ECLEVEL_L => "L",
    Printer::QR_ECLEVEL_M => "M",
    Printer::QR_ECLEVEL_Q => "Q",
    Printer::QR_ECLEVEL_H => "H");
foreach ($ec as $level => $name) {
    $printer -> qrCode($testStr, $level);
    $printer -> text("Error correction $name\n");
    $printer -> feed();
}

// Change size
title($printer, "Pixel size\n");
$sizes = array(
    1 => "(minimum)",
    2 => "",
    3 => "(default)",
    4 => "",
    5 => "",
    10 => "",
    16 => "(maximum)");
foreach ($sizes as $size => $label) {
    $printer -> qrCode($testStr, Printer::QR_ECLEVEL_L, $size);
    $printer -> text("Pixel size $size $label\n");
    $printer -> feed();
}

// Change model
title($printer, "QR model\n");
$models = array(
    Printer::QR_MODEL_1 => "QR Model 1",
    Printer::QR_MODEL_2 => "QR Model 2 (default)",
    Printer::QR_MICRO => "Micro QR code\n(not supported on all printers)");
foreach ($models as $model => $name) {
    $printer -> qrCode($testStr, Printer::QR_ECLEVEL_L, 3, $model);
    $printer -> text("$name\n");
    $printer -> feed();
}
*/
