# Copyright 2017-2018, 2020, 2025 NXP
# SPDX-License-Identifier: BSD-3-Clause

"""
    Implementation of Flash Programmer utility methods

Copyright 2015-2016 Freescale Semiconductor, Inc.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of Freescale Semiconductor nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

This software is provided by Freescale Semiconductor "as is" and any
express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall Freescale Semiconductor be liable for any
direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused and
on any theory of liability, whether in contract, strict liability, or tort
(including negligence or otherwise) arising in any way out of the use of
this software, even if advised of the possibility of such damage.

"""

import gdb

from flash.scripts.utils import gdb_execute
from flash.scripts.utils import gdb_warning

from errors import Result, Ok, Error, ErrorCode, safecall

"""
    Configure execution mode synchronous (Flase) or
    asynchronous (True)
"""
__no_wait = False


def sync_execute_remote(command, from_tty = False, to_string = False):
    """
        Synchronous executor for remote commands
    """
    return gdb_execute(command, from_tty, to_string, check_warning = False)

def async_execute_remote(command, from_tty = False, to_string = False):
    """
        Asynchronous executor for remote commands
    """
    status_cmd = 'mon flash status'
    continue_cmd = 'mon flash continue'
    status_done = 'Done'

    #issue command first
    result = execute_remote(command, from_tty, to_string)

    #now get status
    while True:
        status = execute_remote(status_cmd, from_tty, to_string = True)
        if status and status_done in status:
            return result
        else:
            partial_result = execute_remote(continue_cmd, from_tty, to_string = True)
            if partial_result:
                result = (result + partial_result) if result else partial_result
    return result

def execute_remote(command, from_tty = False, to_string = False, \
            no_wait = False):
    """
        Execute a command on remote server
        Base on execution mode set it will execute with in wait (synchronous)
        mode or no wait (asynchronous) mode.
        All flash programmer's operations should execute in no wait mode
    """

    #don't wait for remote part to finish job
    global __no_wait
    if no_wait is True and __no_wait is True:
        return async_execute_remote(command, from_tty, to_string)
    else:
        if no_wait is True and __no_wait is False:
            gdb_warning('Warning: asyncronous mode is off\n')
            gdb_warning('Warning: command %s is executed synchronous \n' % command)
        return sync_execute_remote(command, from_tty, to_string)

def set_execute_mode(no_wait):
    global __no_wait
    __no_wait = no_wait

    if no_wait:
        execute_remote('mon flash async true')
    else:
        execute_remote('mon flash async false')

def cancel_execute_remote(from_tty = False):
    sync_execute_remote('mon flash cancel', from_tty)
    gdb.write('Operation canceled\n')
