#!/usr/bin/env perl

use 5.012;
use warnings;
no warnings 'uninitialized';
use Data::Dumper;

use Carp;
use Encode;
use Encode::CN;
use YAML;
use YAML::Loader;

use File::Slurp;
use Config::Tiny;
use Cwd qw'cwd abs_path';
use File::Basename;
use Huawei::Info::Ipaddr;
use POSIX qw/strftime/;
use Spreadsheet::WriteExcel;

#初始化本地时间
my $time = strftime( "%Y%m%d", localtime() );

#获取当前脚本绝对路径
my $dir = dirname( abs_path($0) );

#指定系统路径分隔符
my $split = "\\";

#初始化相关变量
my ( $config_dir, $report_dir );

#设置配置文件路径
my $config_ini = $dir . $split . "config.ini";

#------------------------------------------------------------------------------
#机房数据映射哈希
#------------------------------------------------------------------------------
my %location = (
  "chaosuan"    => "超算机房",
  "pengboshi"   => "鹏博士机房",
  "huitian"     => "汇天机房",
  "chaoyangmen" => "朝阳门机房",
);

#------------------------------------------------------------------------------
#初始化配置文件路径
#------------------------------------------------------------------------------
sub create_ini {

  #配置文件初始化
  my $text = '#配置目录文件夹
config_dir = config
report_dir = report
';

  #将配置文件转码未CP936
  $text = encode( "cp936", decode_utf8("$text") );

  #判断INI配置文件是否存在
  write_file( $config_ini, $text );
}

#------------------------------------------------------------------------------
#防火墙配置解析准备
#------------------------------------------------------------------------------
sub prepare {

  #初始化配置文件
  create_ini() unless -f $config_ini;
  my $config = new Config::Tiny->read($config_ini);

  #如果实例化成功则croak
  croak encode( "cp936", decode_utf8("请检查配置文件是否存在") )
    unless $config;

  #网络配置文件夹
  $config_dir = $dir . $split . $config->{"_"}{"config_dir"};

  #报表输出文件夹
  $report_dir = $dir . $split . $config->{"_"}{"report_dir"};

  #检查相关文件夹是否存在,不存在则新建
  mkdir $config_dir unless -d $config_dir;
  mkdir $report_dir unless -d $report_dir;
}

#------------------------------------------------------------------------------
#将数据写入EXCEL表格
#------------------------------------------------------------------------------
sub write_excel {

  #接收外部传递的配置文件夹
  my $rev = shift;

  #获取计算结果
  my $ret = arp_mac_info($rev);

  #网络设备本身IP信息
  my $ret1 = $ret->[0];

  #接入层交换机MAC信息
  my $ret2 = $ret->[1];

  #获取解析到的IP并打印
  my $ret1_count = scalar( keys %{$ret1} );
  my $ret2_count = scalar( keys %{$ret2} );

  #打印扫描到的IP数量
  say encode( "cp936", decode_utf8("共扫描到 $ret1_count 个网络设备IP") );
  say encode( "cp936", decode_utf8("共扫描到 $ret2_count 个服务器IP") );

  #创建EXCEL表格
  my $wb_name = "数据中心_IP地址归属表" . "_$time" . '.xls';
  $wb_name = encode( "cp936", decode_utf8($wb_name) );

  #设备绝对路径
  my $filename = $report_dir . $split . $wb_name;
  my $workbook = Spreadsheet::WriteExcel->new($filename);

  #新建sheet
  my $sheet1 = decode_utf8('网络设备IP地址定位表');
  my $sheet2 = decode_utf8('接入层交换机IP定位表');

  my $worksheet1 = $workbook->add_worksheet($sheet1);
  my $worksheet2 = $workbook->add_worksheet($sheet2);

  #设置表单格式
  my $format = $workbook->add_format();
  $format->set_bold();
  $format->set_color('purple');
  $format->set_bg_color('orange');
  $format->set_size(16);
  $format->set_border(1);
  $format->set_align('center');
  $format->set_valign('vcenter');

  my $format_1 = $workbook->add_format();
  $format_1->set_size(12);
  $format_1->set_border(1);
  $format_1->set_align('center');
  $format_1->set_valign('vcenter');

  my $format_2 = $workbook->add_format();
  $format_2->set_size(12);
  $format_2->set_align('center');
  $format_2->set_valign('vcenter');

  #设置格式
  $worksheet1->set_column( 0, 5, 28.5, $format_2 );
  $worksheet2->set_column( 0, 5, 28.5, $format_2 );

  #创建表单-表头
  my $excel_array = [
    decode_utf8("IP地址"),      decode_utf8("关联设备"),
    decode_utf8("关联接口"),  decode_utf8("MAC地址"),
    decode_utf8("所属VLAN|BD"), decode_utf8("所在机房"),
  ];
  $worksheet1->write_row( 0, 0, $excel_array, $format );
  $worksheet2->write_row( 0, 0, $excel_array, $format );

  #sheet1写入数据
  my $row1 = 1;
  foreach my $ip ( sort ( keys %{$ret1} ) ) {

    #获取解析结果并分解
    my $ip_info   = $ret1->{$ip};
    my $ipaddr    = $ip_info->{"ip"};
    my $hostname  = $ip_info->{"hostname"};
    my $interface = $ip_info->{"interface"};
    my $mac       = $ip_info->{"mac"};
    my $vlan      = $ip_info->{"vlan"};
    my $dc_code   = $ip_info->{"location"};

    #转换机房数据字典
    my $location;
    if ( exists $location{$dc_code} ) {
      $location = $location{$dc_code};
      $location = decode_utf8($location);
    }
    else {
      $location = decode_utf8("非标命名未解析成功");
    }

    #临时封装匿名数组
    my $array = [ $ipaddr, $hostname, $interface, $mac, $vlan, $location ];

    #写入计算数据
    $worksheet1->set_row( $row1, 22.5 );
    $worksheet1->write_row( $row1, 0, $array, $format_1 );
    $row1++;
  }

  #sheet2写入数据
  my $row2 = 1;
  foreach my $ip ( sort ( keys %{$ret2} ) ) {

    #获取解析结果并分解
    my $ip_info   = $ret2->{$ip};
    my $ipaddr    = $ip_info->{"ip"};
    my $hostname  = $ip_info->{"hostname"};
    my $interface = $ip_info->{"interface"};
    my $mac       = $ip_info->{"mac"};
    my $vlan      = $ip_info->{"vlan"};
    my $dc_code   = $ip_info->{"location"};

    #转换机房数据字典
    my $location;
    if ( exists $location{$dc_code} ) {
      $location = $location{$dc_code};
      $location = decode_utf8($location);
    }
    else {
      $location = decode_utf8("非标命名未解析成功");
    }

    #临时封装匿名数组
    my $array = [ $ipaddr, $hostname, $interface, $mac, $vlan, $location ];

    #写入计算数据
    $worksheet2->set_row( $row2, 22.5 );
    $worksheet2->write_row( $row2, 0, $array, $format_1 );
    $row2++;
  }

  #持久化数据结构
  my $yaml = "数据中心_IP归属查询.yaml";
  $yaml = $report_dir . $split . $yaml;
  $yaml = encode( "cp936", decode_utf8($yaml) );
  YAML::DumpFile( $yaml, $ret );
}

#------------------------------------------------------------------------------
#实际处理函数
#------------------------------------------------------------------------------
prepare();
write_excel($config_dir);