#! /usr/bin/perl

use strict;
use warnings;
use Gtk3 -init;
use Glib qw(TRUE FALSE);
use IPC::Open3;
use IO::Select;
use Symbol qw(gensym);

use strict;
use warnings;
use Exporter qw(import);

our @EXPORT_OK = qw(get_disks);

# 获取系统中的硬盘列表（只显示盘和大小，不显示分区）
sub get_disks {
    my @disks;
    
    # 在Linux系统上，使用lsblk命令获取硬盘信息
    if ($^O eq 'linux') {
        open(my $fh, "lsblk -d -n -o NAME,SIZE,TYPE |") or die "cannot execute lsblk: $!";
        while (my $line = <$fh>) {
            chomp $line;
            if ($line =~ /^(\S+)\s+(\S+)\s+disk/) {
                my ($name, $size) = ($1, $2);
                push @disks, {
                    device => "/dev/$name",
                    size => $size
                };
            }
        }
        close($fh);
    }
    return \@disks;
}

# 创建一个GTK窗口来显示命令输出
sub create_output_window {
    my ($cmd, $title) = @_;
    
    # 创建一个新窗口
    my $output_window = Gtk3::Window->new('toplevel');
    $output_window->set_title($title || "Command Output");
    $output_window->set_default_size(700, 400);
    $output_window->set_position('center');
    $output_window->set_keep_above(TRUE);
    
    # 创建垂直布局
    my $vbox = Gtk3::Box->new('vertical', 5);
    $vbox->set_margin_top(10);
    $vbox->set_margin_bottom(10);
    $vbox->set_margin_start(10);
    $vbox->set_margin_end(10);
    $output_window->add($vbox);
    
    # 创建滚动窗口
    my $scrolled_window = Gtk3::ScrolledWindow->new();
    $scrolled_window->set_policy('automatic', 'automatic');
    $vbox->pack_start($scrolled_window, TRUE, TRUE, 0);
    
    # 创建文本视图
    my $text_view = Gtk3::TextView->new();
    $text_view->set_editable(FALSE);
    $text_view->set_cursor_visible(FALSE);
    $text_view->set_monospace(TRUE);
    $text_view->set_wrap_mode('word');
    
    # 设置文本颜色为绿色，背景为黑色（类似终端）
    my $buffer = $text_view->get_buffer();
    my $green_tag = $buffer->create_tag('green_text', 
        font => 'Monospace 10'
    );
    $buffer->apply_tag($green_tag, $buffer->get_start_iter(), $buffer->get_end_iter());
    
    $scrolled_window->add($text_view);
    # 添加关闭按钮
    my $button_box = Gtk3::Box->new('horizontal', 5);
    $button_box->set_halign('end');
    $vbox->pack_start($button_box, FALSE, FALSE, 0);
    
    my $close_button = Gtk3::Button->new_with_label("Close");
    $close_button->signal_connect('clicked' => sub {
        $output_window->destroy();
    });
    $button_box->pack_start($close_button, FALSE, FALSE, 0);
    
    # 显示窗口
    $output_window->show_all();
    
    # 启动命令并捕获输出
    my ($in, $out, $err);
    $err = gensym;
    
    # 创建子进程运行命令
    my $pid = open3($in, $out, $err, $cmd);
    
    # 设置非阻塞
    use Fcntl;
    my $flags;
    fcntl($out, F_GETFL, $flags);
    fcntl($out, F_SETFL, $flags | O_NONBLOCK);
    fcntl($err, F_GETFL, $flags);
    fcntl($err, F_SETFL, $flags | O_NONBLOCK);
    
    # 使用IO::Select监控文件句柄
    my $sel = IO::Select->new();
    $sel->add($out, $err);
    
    # 创建Glib超时回调来检查输出
    Glib::Timeout->add(100, sub {
        # 检查是否还有要读取的数据
        my @ready = $sel->can_read(0);
        return TRUE unless @ready; # 没有数据时继续等待
        
        foreach my $fh (@ready) {
            my $line = "";
            my $bytes = sysread($fh, $line, 4096);
            
            if ($bytes) {
                # 获取buffer末尾
                my $end_iter = $buffer->get_end_iter();
                
                # 插入文本
                $buffer->insert($end_iter, $line);
                
                # 重新应用绿色标签
                $buffer->apply_tag($green_tag, $buffer->get_start_iter(), $buffer->get_end_iter());
                
                # 自动滚动到底部
                my $mark = $buffer->create_mark('scroll', $buffer->get_end_iter(), FALSE);
                $text_view->scroll_to_mark($mark, 0.0, TRUE, 0.0, 1.0);
                $buffer->delete_mark($mark);
            }
        }
        
        # 检查进程是否还在运行
        my $wait = waitpid($pid, 1); # 非阻塞检查
        if ($wait == $pid) {
            # 进程已结束
            my $status = $? >> 8;
            my $end_iter = $buffer->get_end_iter();
            $buffer->insert($end_iter, "\n\nInstallation process has ended, exit status code: $status\n");
            $buffer->apply_tag($green_tag, $buffer->get_start_iter(), $buffer->get_end_iter());
            
            # 移除IO监视器
            $sel->remove($out, $err);
            close($in);
            close($out);
            close($err);
            
            return FALSE; # 结束定时器
        }
        
        return TRUE; # 继续定时器
    });
    
    return $output_window;
}

# 创建主窗口
my $window = Gtk3::Window->new('toplevel');
$window->set_title('PXVDI Installer');
$window->set_default_size(600, 400);
$window->set_border_width(10);
$window->signal_connect('destroy' => sub { Gtk3::main_quit() });

# 设置窗口固定大小，不允许调整
$window->set_resizable(FALSE);
# 设置窗口保持在最前面
# $window->set_keep_above(TRUE);
# 设置窗口位置在屏幕中央
$window->set_position('center');

# 创建垂直布局容器
my $vbox = Gtk3::Box->new('vertical', 10);
$window->add($vbox);

# 1. 标题部分
my $title_label = Gtk3::Label->new();
$title_label->set_markup('<span size="x-large" weight="bold">PXVDI Installer</span>');
$title_label->set_margin_top(10);
$title_label->set_margin_bottom(20);
$vbox->pack_start($title_label, FALSE, FALSE, 0);

# 2. 安装方式选择部分
my $method_frame = Gtk3::Frame->new('Install Method Selection');
$vbox->pack_start($method_frame, FALSE, FALSE, 0);

my $method_box = Gtk3::Box->new('vertical', 10);
$method_box->set_margin_top(10);
$method_box->set_margin_bottom(10);
$method_box->set_margin_start(10);
$method_box->set_margin_end(10);
$method_frame->add($method_box);

# 创建安装方式选择的列表存储
my $method_store = Gtk3::ListStore->new('Glib::String');
my $iter1 = $method_store->append();
$method_store->set($iter1, 0, 'Snapshot Install');
my $iter2 = $method_store->append();
$method_store->set($iter2, 0, 'Traditional Install');

# 创建下拉选择框
my $method_combo = Gtk3::ComboBox->new_with_model($method_store);
my $method_renderer = Gtk3::CellRendererText->new();
$method_combo->pack_start($method_renderer, TRUE);
$method_combo->add_attribute($method_renderer, 'text', 0);
$method_combo->set_active(0); # 默认选择第一项

$method_box->pack_start(Gtk3::Label->new('Select Install Method:'), FALSE, FALSE, 5);
$method_box->pack_start($method_combo, FALSE, FALSE, 5);

# 3. 硬盘选择部分
my $disk_frame = Gtk3::Frame->new('Select Install Disk');
$vbox->pack_start($disk_frame, FALSE, FALSE, 0);

my $disk_box = Gtk3::Box->new('vertical', 10);
$disk_box->set_margin_top(10);
$disk_box->set_margin_bottom(10);
$disk_box->set_margin_start(10);
$disk_box->set_margin_end(10);
$disk_frame->add($disk_box);

# 获取硬盘列表
my $disk_store = Gtk3::ListStore->new('Glib::String', 'Glib::String');
my $disks = get_disks();
foreach my $disk (@$disks) {
    my $iter = $disk_store->append();
    $disk_store->set($iter, 
        0, $disk->{device}, 
        1, $disk->{size}
    );
}

# 创建下拉选择框
my $disk_combo = Gtk3::ComboBox->new_with_model($disk_store);
my $renderer = Gtk3::CellRendererText->new();
$disk_combo->pack_start($renderer, TRUE);
$disk_combo->add_attribute($renderer, 'text', 0);

# 添加大小显示
my $size_renderer = Gtk3::CellRendererText->new();
$disk_combo->pack_start($size_renderer, TRUE);
$disk_combo->add_attribute($size_renderer, 'text', 1);

$disk_box->pack_start(Gtk3::Label->new('Select Install Disk:'), FALSE, FALSE, 0);
$disk_box->pack_start($disk_combo, FALSE, FALSE, 0);

# 4. 确认按钮部分
my $button_box = Gtk3::Box->new('horizontal', 0);
$button_box->set_halign('end');
$button_box->set_margin_top(20);
$vbox->pack_start($button_box, FALSE, FALSE, 0);

my $install_button = Gtk3::Button->new_with_label('Confirm Install');
$install_button->signal_connect('clicked' => \&on_install_clicked);
$button_box->pack_start($install_button, FALSE, FALSE, 0);

# 确认按钮点击事件处理函数（由用户自行实现）
sub on_install_clicked {
    my $selected_iter = $disk_combo->get_active_iter();
    
    if (!$selected_iter) {
        my $dialog = Gtk3::MessageDialog->new(
            $window, 
            [qw/modal destroy-with-parent/],
            'error',
            'ok',
            'Please select the install disk'
        );
        # 设置错误对话框固定大小，保持在最前面
        $dialog->set_resizable(FALSE);
        $dialog->set_keep_above(TRUE);
        $dialog->set_default_size(300, 120);
        
        $dialog->run();
        $dialog->destroy();
        return;
    }
    
    my $selected_disk = $disk_store->get($selected_iter, 0);
    
    # 获取选择的安装方式
    my $method_iter = $method_combo->get_active_iter();
    my $install_type = $method_store->get($method_iter, 0);
    my $type = 'snapshot';
    if ($install_type eq 'Traditional Install') {
        $type = 'traditional';
    }
    my $disk_name = $selected_disk;
    my $dialog = Gtk3::MessageDialog->new(
        $window,
        [qw/modal destroy-with-parent/],
        'question',
        'yes-no',
        "Confirm to install PXVDI on $disk_name using $type method?"
    );
    
    # 设置对话框固定大小，保持在最前面
    $dialog->set_resizable(FALSE);
    $dialog->set_keep_above(TRUE);
    $dialog->set_default_size(400, 150);
    
    my $response = $dialog->run();
    if ($response eq 'yes') {
        # 关闭当前对话框
        $dialog->destroy();
        
        if ($type eq 'snapshot') {
            # 创建显示安装过程的窗口
            my $install_cmd = "";
            if ( -f "/usr/bin/pxvdi-install" ) {
                $install_cmd = "/usr/bin/pxvdi-install $disk_name";
            } else {
                $install_cmd = "/usr/bin/pxvdi-install-old $disk_name";
            }
            
            # 使用自定义窗口显示安装过程
            my $output_window = create_output_window($install_cmd, "PXVDI Installation");
        }
    } else {
        $dialog->destroy();
        return;
    }
}

# 显示窗口
$window->show_all();

# 启动主循环
Gtk3::main(); 