/********************************************************
 *  ██████╗  ██████╗████████╗██╗
 * ██╔════╝ ██╔════╝╚══██╔══╝██║
 * ██║  ███╗██║        ██║   ██║
 * ██║   ██║██║        ██║   ██║
 * ╚██████╔╝╚██████╗   ██║   ███████╗
 *  ╚═════╝  ╚═════╝   ╚═╝   ╚══════╝
 * Geophysical Computational Tools & Library (GCTL)
 *
 * Copyright (c) 2023  Yi Zhang (yizhang-geo@zju.edu.cn)
 *
 * GCTL is distributed under a dual licensing scheme. You can redistribute 
 * it and/or modify it under the terms of the GNU Lesser General Public 
 * License as published by the Free Software Foundation, either version 2 
 * of the License, or (at your option) any later version. You should have 
 * received a copy of the GNU Lesser General Public License along with this 
 * program. If not, see <http://www.gnu.org/licenses/>.
 * 
 * If the terms and conditions of the LGPL v.2. would prevent you from using 
 * the GCTL, please consider the option to obtain a commercial license for a 
 * fee. These licenses are offered by the GCTL's original author. As a rule, 
 * licenses are provided "as-is", unlimited in time for a one time fee. Please 
 * send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget 
 * to include some description of your company and the realm of its activities. 
 * Also add information on how to contact you by electronic and paper mail.
 ******************************************************/

#include "process_monitor.h"

int scan_keyboard()
{
    int in = 0;
    struct termios new_settings;
    struct termios stored_settings;
    tcgetattr(0,&stored_settings);
    new_settings = stored_settings;
    new_settings.c_lflag &= (~ICANON);
    new_settings.c_cc[VTIME] = 0;
    tcgetattr(0,&stored_settings);
    new_settings.c_cc[VMIN] = 1;
    tcsetattr(0,TCSANOW,&new_settings);
    in = getchar();
    tcsetattr(0,TCSANOW,&stored_settings);
    return in;
}

gctl::process_monitor::process_monitor()
{
    end_process_ = false;
}

gctl::process_monitor::~process_monitor()
{
}

void gctl::process_monitor::set_end_process(bool ask)
{
    if (ask)
    {
        std::string key;
        std::cout << "Quit? (y/n): ";
        std::cin >> key;
        if (key == "y") end_process_ = true;
    }
    else
    {
        std::clog << "Press any key to quit.\n";
        end_process_ = true;
    }
	return;
}

void gctl::process_monitor::start_monitoring()
{
    // start a new thread for inversion
    std::thread ttd = process_wapper();
    // start the monitoring function
    keyboard_actions();
    // wait for the inversion to finish
    ttd.join();
    return;
}

void gctl::process_monitor::wait_for_kerboard(int sec)
{
    // 键盘事件受到 keyboard_actions 的监控
    std::cout << "Press 'p' to pause. Continue in " << sec << " seconds ..." << std::endl;

	std::unique_lock<std::mutex> lck(mtx_); // 设置锁 等待监控函数的响应 如果超时则继续
	if (cv_.wait_for(lck, std::chrono::seconds(sec)) == std::cv_status::timeout)
	{
		std::clog << "\x1b[1A\r\x1b[K";
	}
    return;
}

void gctl::process_monitor::keyboard_actions()
{
    while (!end_process_)
	{
		int key_value = scan_keyboard();
		std::string key_str;
		if (key_value == 112) // p的键值为112
		{
			std::unique_lock<std::mutex> lck(mtx_);

            // 这里可以设置额外的条件和命令
			std::cout << "\rInput 'q' to quit: ";
			std::cin  >> key_str;

            // 执行更多的命令
			if (key_str == "q") set_end_process(true);
			cv_.notify_one();
		}
	}
	return;
}

bool gctl::process_monitor::end_process()
{
    return end_process_;
}