# coding: utf-8
# python 2 only

# Copyright (c) 2026 TormachTips.com. All rights reserved.
# Licensed under the TormachTips Personal Use License.
# Permission is granted only for private personal use and private personal modification.
# No sharing, publication, distribution, resale, sublicensing, screenshots, code excerpts,
# benchmarks, or videos are permitted without prior written permission.
# Requests:         tormach.1100m@gmail.com
# Information page: https://tormachtips.com/plugins.htm

#############################################
##                                         ##
##     File Run History Plugin v0.98       ##
##          www.tormachtips.com            ##
##                                         ##
#############################################

# 0.98 - removed an ALARM_LEVEL_LOW to not annoy us - 4/6/26
# 0.95 - public release - 3/1/26

## DESCRIPTION:
##   This PathPilot plugin automatically keeps a permanent copy of the gcode log
##   by syncing /home/operator/gcode/logfiles/gcode_log.txt with
##   /home/operator/gcode/python/tormachtips_gcode_log.txt once per hour.

## WHY THIS EXISTS:
##   PathPilot periodically rotates the master log file. If you only open File Run History
##   plugin occasionally, you may miss file run history. This plugin guarantees
##   the permanent archive always contains everything, even after rotations or truncs.
##   This plugin is technically optional if you regularly open the File Run History script.

## HOW IT WORKS:
##   - Runs as a background daemon thread 
##   - First sync happens 10 seconds after PathPilot starts
##   - Then repeats every INTERVAL seconds (default = 3600 = 1 hour)
##   - Safe even if the master log is being written to at the same time

## The standalone File Run History Viewer will now always see the complete
## history because it reads from the permanent archive instead of the possibly-rotated master file.

import os
import time
import glib
import threading
import constants
from ui_hooks import plugin

CURRENT_VER       = "0.98"
SCRIPT_NAME       = "File Run History Logger Plugin"
DESCRIPTION       = "Monitors completed NC programs and logs them for future analysis."
OEM_GCODE_LOG     = '/home/operator/gcode/logfiles/gcode_log.txt'
ARCHIVE_GCODE_LOG = '/home/operator/gcode/python/tormachtips_gcode_log.txt'
INTERVAL_SEC      = 600
ENABLED           = 1
DEV_MACHINE       = 1
DEV_MACHINE_FLAG  = "/home/operator/gcode/python/dev_machine.txt"

def sync_archive_log(live_log_path, archive_log_path):
    if not os.path.isfile(live_log_path):
        return 0
    live_lines = []
    try:
        f_live = open(live_log_path, 'r')
        try:
            live_lines = f_live.readlines()
        finally:
            f_live.close()
    except:
        return 0
    if not os.path.isfile(archive_log_path):
        try:
            f_archive = open(archive_log_path, 'w')
            try:
                f_archive.writelines(live_lines)
            finally:
                f_archive.close()
            return len(live_lines)
        except:
            return 0
    archive_seen = {}
    try:
        f_archive = open(archive_log_path, 'r')
        try:
            for line in f_archive:
                archive_seen[line] = True
        finally:
            f_archive.close()
    except:
        return 0
    new_lines = []
    for line in live_lines:
        if line not in archive_seen:
            new_lines.append(line)
            archive_seen[line] = True
    if not new_lines:
        return 0
    try:
        f_archive = open(archive_log_path, 'a')
        try:
            f_archive.writelines(new_lines)
        finally:
            f_archive.close()
        return len(new_lines)
    except:
        return 0

class UserPlugin(plugin):
    def __init__(self):
        plugin.__init__(self, 'Gcode Log Auto Archive')
        dev_machine_found = os.path.exists(DEV_MACHINE_FLAG)
        if dev_machine_found:
            plugin_enabled = DEV_MACHINE
        else:
            plugin_enabled = ENABLED
        if plugin_enabled:
            glib.timeout_add(10000, self.perform_sync)
            self.worker_thread = threading.Thread(target=self.interval_worker)
            self.worker_thread.daemon = True
            self.worker_thread.start()
            return
        else:
            if dev_machine_found:
                self.error_handler.write("[Gcode Log Auto Archive] Dev machine found. Plugin loaded, but disabled by DEV_MACHINE.", constants.ALARM_LEVEL_QUIET)
            else:
                self.error_handler.write("[Gcode Log Auto Archive] Plugin loaded, but disabled.", constants.ALARM_LEVEL_QUIET)
                self.error_handler.write("[Gcode Log Auto Archive] To enable, open script, find ENABLED = 0 and change to ENABLED = 1", constants.ALARM_LEVEL_QUIET)
            return
    
    def interval_worker(self):
        while True:
            time.sleep(INTERVAL_SEC)
            glib.idle_add(self.perform_sync)
    
    def perform_sync(self):
        self.error_handler.write("[Gcode Log Auto Archive] Syncing master log to permanent archive...",constants.ALARM_LEVEL_QUIET)
        new_count = sync_archive_log(OEM_GCODE_LOG, ARCHIVE_GCODE_LOG)
        if new_count > 0:
            self.error_handler.write("[Gcode Log Auto Archive] Added {} new line(s) to permanent archive".format(new_count),constants.ALARM_LEVEL_QUIET)
        else:
            self.error_handler.write("[Gcode Log Auto Archive] No new entries (archive is up-to-date)",constants.ALARM_LEVEL_QUIET)
        return False
        
DESCRIPTION_LONG = """This script will parse a log file that 
    contains the NC programs you have opened and run. It will display elapsed 
    time and if it was a Partial or Complete run. It is sorted by Day and you 
    can view whatever day you want. </font></p>
    <p><font face="Verdana" size="2">If you have
    <a href="plugins/custom_admin_commands.py">Custom Admin Commands</a> (and
    <a href="plugins/custom_admin_commands_plugin.py">required file</a>) 
    installed, you can reach it via ADMIN HISTORY. Otherwise, run it from 
    terminal. </font></p>
    <p><a href="images/runhistory2.jpg">
    <img border="2" src="images/runhistory2_small.jpg" xthumbnail-orig-image="images/runhistory2.jpg" width="200" height="150"></a>
    <a href="images/runhistory1.jpg">
    <img border="2" src="images/runhistory1_small.jpg" xthumbnail-orig-image="images/runhistory1.jpg" width="200" height="150"></a>"""        