# Copyright 2024 Windell H. Oskay, Bantam Tools
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

"""
plot_warnings.py

Classes for managing and outputting NextDraw text warnings

Part of the NextDraw driver software
http://bantamtools.com

"""

def layer_name_text(layer_name):
    '''Format layer name text for displaying in warning messages'''
    if layer_name == '__digest-root__':
        return " found in the document root."
    if layer_name.strip() == '':
        return "."
    return " in a layer named " + layer_name.strip() + "."

class PlotWarnings:
    """
    PlotWarnings: Class for managing and outputting warning text messages
    """

    def __init__(self):
        self.warning_dict = {} # Dict for warnings; only store the first warning of each type.
        self.suppress_list = [] # List of warnings that will be suppressed (not reported).

    def reset(self):
        '''Clear the warnings dictionary'''
        self.warning_dict.clear()

    def add_new(self, warning_name, value="1"):
        '''
        Add a warning if that warning type is not already in the dictionary.
        The default value "1" will cause error types of voltage, bounds to be reported.
        For other types (image, text, unknown object), the value should reference the
        SVG layer where the object was detected.
        '''
        if warning_name not in self.warning_dict:
            self.warning_dict[warning_name] = value

    def suppress(self, warning_name):
        '''
        Disable reporting of a specific warning type.
        Use "__all__" as the warning name argument to suppress *all* warnings.
        '''
        self.suppress_list.append(warning_name)

    def return_text_list(self):
        '''Return a list of formatted warning strings'''
        warning_text_list = []

        if '__all__' in self.suppress_list:
            return warning_text_list

        if 'homing_voltage' in self.warning_dict:
            if 'homing_voltage' not in self.suppress_list:
                warning_text_list.append(
                    "Automatic homing failed with an apparent power issue.\n" +
                    "Check that your machine is plugged in and powered on.\n"
                )
            self.warning_dict.pop('homing_voltage')
            try:
                self.warning_dict.pop('voltage')
            except KeyError:
                pass # Sometimes there is not also a voltage warning. That's OK.
        elif 'voltage' in self.warning_dict: # Don't report voltage twice.
            if 'voltage' not in self.suppress_list:
                warning_text_list.append(
                    "Note (voltage): Low voltage detected.\n" +
                    "Check that power supply is plugged in and machine is powered on.\n"
                )
            self.warning_dict.pop('voltage')

        if 'bounds' in self.warning_dict:
            if 'bounds' not in self.suppress_list:
                warning_text_list.append(
                    "Warning (bounds):\n"+\
                    "NextDraw movement was limited by its physical range of motion.\n" +\
                    "If everything else looks correct, there may be an issue with the\n" +\
                    "document size, or you may have the wrong model of plotter\n" +\
                    f"({self.warning_dict['bounds']}) selected." +
                    "\nPlease contact technical support if you need assistance.\n"
                )
                # TODO: Rework this dialog to specify which machine is selected.
            self.warning_dict.pop('bounds')

        if 'image' in self.warning_dict:
            if 'image' not in self.suppress_list:
                warning_text_list.append(
                    'Note (image): This file contains a bitmap image' +
                    layer_name_text(self.warning_dict['image']) +
                    "\nPlease convert images to vectors before plotting." +
                    "\nConsider using the Inkscape Path > Trace Bitmap tool.\n"
                    )
            self.warning_dict.pop('image')

        if 'text' in self.warning_dict:
            if 'text' not in self.suppress_list:
                warning_text_list.append(
                    'Note (plain-text): This file contains some plain text\n' +
                    layer_name_text(self.warning_dict['text']) +
                    "\nPlease convert text into vector paths before plotting." +
                    "\nConsider using the Inkscape Path > Object to Path tool." +
                    "\nAlternately, consider using NextDraw Merge or Hershey Text"+
                    "\nto render your text with stroke-based fonts.\n"
                )
            self.warning_dict.pop('text')

        for object_type, layer_location in self.warning_dict.items():
            # Handle any remaining unknown objects
            if object_type in self.suppress_list:
                continue
            warning_text_list.append(
                'Note (object): Unable to plot ' + object_type + ' object' +
                layer_name_text(layer_location) +
                "\nPlease convert it to a path prior to plotting, and/or " +
                "contact technical support if you need assistance.\n"
            )

        return warning_text_list

    def report(self, suppress, message_fun):
        '''Print warning messages to the given message function'''
        if not suppress:
            for warning_message in self.return_text_list():
                message_fun(warning_message)
