/********************************************************
 *  ██████╗  ██████╗████████╗██╗
 * ██╔════╝ ██╔════╝╚══██╔══╝██║
 * ██║  ███╗██║        ██║   ██║
 * ██║   ██║██║        ██║   ██║
 * ╚██████╔╝╚██████╗   ██║   ███████╗
 *  ╚═════╝  ╚═════╝   ╚═╝   ╚══════╝
 * 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.
 ******************************************************/

#ifndef _GCTL_PROCESS_MONITOR_H
#define _GCTL_PROCESS_MONITOR_H

#include <thread>
#include <mutex>
#include <condition_variable>
#include <termios.h>
#include <iostream>

namespace gctl
{
    class process_monitor
    {
    public:
        process_monitor();
        virtual ~process_monitor();

        /**
         * @brief Implement the process that you want to be monitored here.
         * This is just an API here. A template is shown as bellow:
         * 
         * void process()
         * {
         *     while (1)
         *     {
         *         // do something here
         *         ....
         *         ....
         * 
         *         wait_for_kerboard();
         *         if (end_process()) break;
         *     }
         * 
         *     set_end_process();
         *     return;
         * }
         */
        virtual void process() = 0;

        /**
         * @brief Start the monitoring process.
         * 
         */
        virtual void start_monitoring();

        /**
         * @brief Waiting the keyboard input to pause.
         * 
         * @param sec wait time.
         */
        virtual void wait_for_kerboard(int sec = 1);

        /**
         * @brief Implement excepted actions here when 'p' is pressed.
         * 
         */
        virtual void keyboard_actions();

        /**
         * @brief Check to see if the process is set to end.
         * 
         */
        virtual bool end_process();

        /**
         * @brief Set the end process object to true.
         * 
         * @param ask Ask before setting the end process object to true.
         */
        void set_end_process(bool ask = false);

    private:

        std::thread process_wapper()
        {
            return std::thread(&process_monitor::process, this);
        }

        bool end_process_;
        std::mutex mtx_;
        std::condition_variable cv_;
    };
};

#endif // _GCTL_PROCESS_MONITOR_H