<?php

namespace Hwapx\Logs\Controller\Admin;

use Hwapx\Admin\Controller\Admin\Admin;
use Hwapx\Core\Library\Template;

use F3;
use Log;

class Logs extends Admin {
  protected $log_types = array(
      'error'  => 'Erro',
      'access' => 'Acesso',
      'api'    => 'Api',
      'user'   => 'Usuário',
      'role'   => 'Permissão'
    );

  protected $table = array(
      'title'   => 'Lista de Logs',
      'cols'    => array(
          'ord'        => '#',
          'updated_on' => 'Data/Hora',
          'size'       => 'Tamanho',
          'type'       => 'Tipo',
          'id'         => 'Arquivo'
        ),
      'actions' => array(
          array(
              'route'       => 'admin_logs_clear',
              'description' => 'Excluir todos',
              'class'       => 'btn-danger',
              'confirm'     => true,
              'role'        => 'log_remove'
            )
        ),
      'rowactions' => array(
          array(
              'route'       => 'admin_log_view',
              'description' => 'Visualizar',
              'class'       => 'btn-primary',
              'default'     => true
            ),
          array(
              'route'       => 'admin_log_raw',
              'description' => 'RAW',
              'class'       => 'btn-default',
              'default'     => true
            ),
          array(
              'route'       => 'admin_log_remove',
              'description' => 'Remover',
              'class'       => 'btn-danger',
              'confirm'     => true,
              'role'        => 'log_remove'
            )
        ),
      'route' => 'admin_logs'
    );

  protected $table_view = array(
      'title'   => 'Visualizar Log',
      'cols'    => array(
          'id'   => '#',
          'time' => 'Horário',
          'ipv4' => 'IP v4',
          'log'  => 'Log'
        ),
      'actions' => array(
          array(
              'route'       => 'admin_log_remove',
              'description' => 'Excluir',
              'class'       => 'btn-danger',
              'confirm'     => true,
              'role'        => 'log_remove'
            )
        ),
      'rowactions' => array(
          array(
              'route'       => '#ipv4_map',
              'description' => 'Rastrear IP',
              'class'       => 'btn-primary ipv4-localization',
              'modal'       => true
            )
        ),
      'route' => 'admin_log_view'
    );

  protected $table_cron = array(
      'title'   => 'Visualizar Log do cron',
      'cols'    => array(
          'id'       => '#',
          'time'     => 'Data/Hora',
          'job'      => 'Trabalho',
          'duration' => 'Duração',
        ),
      'actions' => array(
          array(
              'route'       => 'admin_log_remove',
              'description' => 'Excluir',
              'class'       => 'btn-danger',
              'confirm'     => true,
              'role'        => 'log_remove'
            )
        ),
      'route' => 'admin_log_view'
    );

  public function __construct($f3) {
    parent::__construct($f3);

    
  }

  public function index($f3) {
    $this->module->checkRole('logs');

    $f3->set('page.title', 'Logs');

    $page     = $f3->exists('PARAMS.page') ? $f3->get('PARAMS.page') - 1 : 0;
    $files    = $this->fileList($f3->get('LOGS'));
    $log_size = 0;
    $max_rows = $f3->get('app.table.rowcount');

    $date_fmt     = $f3->get('app.date.format');
    $datetime_fmt = $f3->get('app.datetime.format');

    $rows = array();
    for($i = 0; $i < count($files); $i++) {
        $file = $files[$i];
        if(preg_match('/^((\\d{4}-\\d\\d-\\d\\d)_([^\\.]+))\\.log$/', $file['name'], $match))
          $rows[] = array(
              'id'         => $match[1],
              'ord'        => $i + 1,
              'created_on' => date($date_fmt, strtotime($match[2])),
              'updated_on' => date($datetime_fmt, filemtime($file['file'])),
              'type'       => isset($this->log_types[$match[3]]) ? $this->log_types[$match[3]] : $match[3],
              'size'       => sprintf('%.2f kb', $file['size'] / 1024)
            );
        else if($file['name'] == 'cron.log') {
          $rows[] = array(
              'id'         => 'cron',
              'ord'        => 0,
              'created_on' => date($datetime_fmt, filectime($file['file'])),
              'updated_on' => date($datetime_fmt, filemtime($file['file'])),
              'type'       => 'cron',
              'size'       => sprintf('%.2f kb', $file['size'] / 1024)
            );
        }

        $log_size += $file['size'];
    }

    if($log_size > 1024*1024)
      flash('warning', sprintf('Os logs atualmente ocupam %.2f mb de espaço em disco.', $log_size / 1024 / 1024));

    $result = array();

    for($i = 0; $i < count($rows); $i++) {
      $row = $rows[$i];

      $pass = true;
      foreach($this->table['cols'] as $field => $label) {
        $cookie = 'COOKIE.table_filter_'.$this->table['route'].'_'.$field;
        if($f3->exists($cookie) && ($val = $f3->get($cookie)) != '')
          if(strpos($row[$field], $val) === FALSE) {
            $pass = false;
            break;
          }
      }

      if($pass)
        $result[] = $row;
    }

    $desc    = $f3->get('COOKIE.table_order_'.$this->table['route']) != 'asc';
    $field   = $f3->get('COOKIE.table_sort_'.$this->table['route']);
    $field   = in_array($field, array_keys($this->table['cols'])) ? $field : 'updated_on';

    if($field)
      if($field == 'created_on' || $field == 'updated_on')
        usort($result, function($f1, $f2) use($field, $desc, $datetime_fmt) { 
                         return $desc ? date_create_from_format($datetime_fmt, $f2[$field])->getTimestamp() - 
                                        date_create_from_format($datetime_fmt, $f1[$field])->getTimestamp() : 
                                        date_create_from_format($datetime_fmt, $f1[$field])->getTimestamp() - 
                                        date_create_from_format($datetime_fmt, $f2[$field])->getTimestamp();
                       });
      else
        usort($result, function($f1, $f2) use($field, $desc) { return $desc ? strcmp($f2[$field], $f1[$field]) : strcmp($f1[$field], $f2[$field]); });

    $this->table['subset'] = array_slice($result, $page * $max_rows, $max_rows);
    $this->table['total']  = count($result);
    $this->table['limit']  = $max_rows;
    $this->table['count']  = ceil($this->table['total'] / $max_rows);
    $this->table['pos']    = $page;

    $f3->set('table', $this->table);

    echo Template::instance()->render('hwapx/admin/admin/table.html');
  }

  public function view($f3) {
    $f3->set('breadcrumbs', array($this->table['route'] => $this->table['title'], 'Visualizar Log'));

    $this->module->checkRole('logs');

    $f3->set('page.title', 'Visualizar Log');

    $file  = $f3->get('LOGS').str_replace(array('\\', '/', '%'), array(), $f3->get('PARAMS.id')).'.log';
    file_exists($file) || $f3->error(404);

    $lines    = file($file);
    $page     = $f3->exists('PARAMS.page') ? $f3->get('PARAMS.page') - 1 : 0;
    $max_rows = 99999999;//$f3->get('app.table.rowcount');

    $time_fmt     = $f3->get('app.time.format');
    $datetime_fmt = $f3->get('app.datetime.format');

    $rows = array();

    for($i = 0; $i < count($lines); $i++) {
        $line = $lines[$i];
        if(preg_match('/^([^\\[]+) \\[([^\\]]+)\\] (.+)$/m', $line, $match))
          $rows[] = array(
              'id'   => $i + 1,
              'time' => date($time_fmt, strtotime($match[1])),
              'ipv4' => $match[2],
              'log'  => $match[3]
            );
    }

    $result = array();

    for($i = 0; $i < count($rows); $i++) {
      $row = $rows[$i];

      $pass = true;
      foreach($this->table_view['cols'] as $field => $label) {
        $cookie = 'COOKIE.table_filter_'.$this->table_view['route'].'_'.$field;
        if($f3->exists($cookie) && ($val = $f3->get($cookie)) != '')
          if(strpos($row[$field], $val) === FALSE) {
            $pass = false;
            break;
          }
      }

      if($pass)
        $result[] = $row;
    }

    $desc    = $f3->get('COOKIE.table_order_'.$this->table_view['route']) != 'asc';
    $field   = $f3->get('COOKIE.table_sort_'.$this->table_view['route']);
    $field   = in_array($field, array_keys($this->table_view['cols'])) ? $field : 'time';

    if($field) {
      if($field == 'time')
        usort($result, function($f1, $f2) use($field, $desc, $time_fmt) { 
                         return $desc ? date_create_from_format($time_fmt, $f2[$field])->getTimestamp() - 
                                        date_create_from_format($time_fmt, $f1[$field])->getTimestamp() : 
                                        date_create_from_format($time_fmt, $f1[$field])->getTimestamp() - 
                                        date_create_from_format($time_fmt, $f2[$field])->getTimestamp();
                       });
      else
        usort($result, function($f1, $f2) use($field, $desc) { return $desc ? strcmp($f2[$field], $f1[$field]) : strcmp($f1[$field], $f2[$field]); });
    }

    $this->table_view['subset'] = array_slice($result, $page * $max_rows, $max_rows);
    $this->table_view['total']  = count($result);
    $this->table_view['limit']  = $max_rows;
    $this->table_view['count']  = ceil($this->table_view['total'] / $max_rows);
    $this->table_view['pos']    = $page;

    $f3->set('table', $this->table_view);

    $f3->push('meta.html', <<<'EOH'
<div id="ipv4_map" class="modal">
  <div class="modal-dialog modal-lg">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Fechar</span></button>
        <h4 class="modal-title">Localização</h4>
      </div>
      <div class="modal-body">
      <iframe id="g_map" height="450" frameborder="0" style="border:0; width: 100%; height: 450px;"></iframe>
      </div>
      <div class="modal-footer">
        <p>A localização exibida é aproximada</p>
        <!--<button type="button" class="btn btn-default" data-dismiss="modal">Fechar</button>-->
      </div>
    </div>
  </div>
</div>
EOH
);

    //$f3->push('scripts.files', 'http://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&sensor=FALSE');
    $f3->push('meta.scripts.raw', <<<'EOS'
      $('.ipv4-localization').click(function() {
        $('#g_map').removeAttr('src');
        var ip = $(this).parents('tr').find('[data-field=ipv4]').html().trim();
        $.get('{{ @BASE }}/api/geoip/' + ip, '', function(response) {
          var lines = response.split('\n');
          var data = {};
          for(i in lines) {
            var d = lines[i].split(': ');
            data[d[0]] = d[1];
          }
          var url = 'https://www.google.com/maps/embed?pb=!1m18!1m8!1m3!1d1896612.6986501275!2d' + data.Longitude + '!3d' + data.Latitude + '!3m2!1i1024!2i768!4f13.1!4m7!1i0!3e6!4m3!3m2!1d' + data.Latitude + '!2d' + data.Longitude + '!4m0!5e0!3m2!1spt-BR!2sbr!4v1414899512091';
          $('#g_map').attr('src', url);
        });
      });
EOS
);

    echo Template::instance()->render('hwapx/admin/admin/table.html');
  }

  public function raw($f3) {
    $f3->set('breadcrumbs', array($this->table['route'] => $this->table['title'], 'Visualizar Log'));

    $this->module->checkRole('logs');

    $f3->set('page.title', 'Visualizar Log');

    $file  = $f3->get('LOGS').str_replace(array('\\', '/', '%'), array(), $f3->get('PARAMS.id')).'.log';
    file_exists($file) || $f3->error(404);

    $handle = fopen($file, 'r');

    header('Content-Type: text/plain');

    fpassthru($handle);
    fclose($handle);
  }

  public function cron($f3) {
    $f3->set('breadcrumbs', array($this->table['route'] => $this->table['title'], 'Visualizar Log'));
    $f3->set('PARAMS.id', 'cron');
    
    $this->module->checkRole('logs');

    $f3->set('page.title', 'Visualizar Log');

    $file  = $f3->get('LOGS').'cron.log';
    file_exists($file) || $f3->error(404);

    $lines    = file($file);
    $page     = $f3->exists('PARAMS.page') ? $f3->get('PARAMS.page') - 1 : 0;
    $max_rows = 100;//$f3->get('app.table.rowcount');

    $time_fmt     = $f3->get('app.time.format');
    $datetime_fmt = $f3->get('app.datetime.format');

    $rows = array();

    for($i = 0; $i < count($lines); $i++) {
        $line = $lines[$i];
        if(preg_match('/^(\w{3}, \d\d \w{3} \d{4} \d\d:\d\d:\d\d [-\d]{5}) ([^ ]+) \(((\d+\.\d+) (\w+))\)$/m', $line, $match))
          $rows[] = array(
              'id'       => $i + 1,
              'time'     => date_create_from_format(DATE_RFC2822, $match[1])->format($datetime_fmt),
              'job'      => $match[2],
              'duration' => $match[3]
            );
    }

    $lines = null;

    $result = array();

    for($i = 0; $i < count($rows); $i++) {
      $row = $rows[$i];

      $pass = true;
      foreach($this->table_cron['cols'] as $field => $label) {
        $cookie = 'COOKIE.table_filter_'.$this->table_cron['route'].'_'.$field;
        if($f3->exists($cookie) && ($val = $f3->get($cookie)) != '')
          if(strpos($row[$field], $val) === FALSE) {
            $pass = false;
            break;
          }
      }

      if($pass)
        $result[] = $row;
    }

    $rows = null;

    $desc    = $f3->get('COOKIE.table_order_'.$this->table_cron['route']) != 'asc';
    $field   = $f3->get('COOKIE.table_sort_'.$this->table_cron['route']);
    $field   = in_array($field, array_keys($this->table_cron['cols'])) ? $field : 'time';

    if($field) {
      if($field == 'time')
        usort($result, function($f1, $f2) use($field, $desc, $datetime_fmt) { 
                         return $desc ? date_create_from_format($datetime_fmt, $f2[$field])->getTimestamp() - 
                                        date_create_from_format($datetime_fmt, $f1[$field])->getTimestamp() : 
                                        date_create_from_format($datetime_fmt, $f1[$field])->getTimestamp() - 
                                        date_create_from_format($datetime_fmt, $f2[$field])->getTimestamp();
                       });
      else
        usort($result, function($f1, $f2) use($field, $desc) { return $desc ? strcmp($f2[$field], $f1[$field]) : strcmp($f1[$field], $f2[$field]); });
    }

    $this->table_cron['subset'] = array_slice($result, $page * $max_rows, $max_rows);
    $this->table_cron['total']  = count($result);
    $this->table_cron['limit']  = $max_rows;
    $this->table_cron['count']  = ceil($this->table_cron['total'] / $max_rows);
    $this->table_cron['pos']    = $page;

    $f3->set('table', $this->table_cron);

    echo Template::instance()->render('hwapx/admin/admin/table.html');
  }

  public function remove($f3) {
    $this->module->checkRole('log_remove');

    $id    = $f3->get('PARAMS.id');
    $file  = $f3->get('LOGS').str_replace(array('\\', '/', '%'), array(), $id).'.log';

    file_exists($file) || $f3->error(404);

    unlink($file);

    flash('success', 'Log '.$id.' removido.');
    $f3->reroute('@admin_logs');
  }

  public function clear($f3) {
    $logs_dir  = $f3->get('LOGS');
    $files     = $this->fileList($logs_dir);

    $size = 0;
    foreach($files as $f) {
      $size += filesize($f['file']);
      unlink($f['file']);
    }

    $msgs = sprintf('%d Arquivos um total de %.2f kb removidos.', count($files), $size / 1024);

    flash('success', $msgs);
    $f3->reroute('@admin_logs');
  }

  protected function fileList($dir) {
    $entries = scandir($dir);

    $files = array();
    foreach($entries as $e) {
      $f = $dir.$e;
      if(is_file($f))
        $files[] = array(
            'name' => $e,
            'file' => $f,
            'size' => filesize($f)
          );
      }

    return $files;
  }

}