# Copyright 2022 Synchronous Technologies Pte Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.



# taken from zef function
# class ToClipboard:
#     def __init__(self):
#         self.__doc__ = 'ABC'
    



#     def _make_header(self, z_zef_function: ZefRef)->str:
#         from zefdb.ops import target, uid, value, collect
#         from zefdb import tools
#         g = Graph(z_zef_function)         
#         # TODO: possibly warn if this is NOT the latest version known at the time of generating this snippet!
#         original_fct_name = z_zef_function >> RT.OriginalName | value | collect if z_zef_function | ops.has_out[RT.OriginalName] | collect else None
#         return "\n".join([
# f"# --------------------------------------------         this code snippet was generated by          --------------------------------------------",
# f"# --------------------------------------------  zefdb.to_clipboard at {str(ops.now())}  --------------------------------------------",
# #f"# origin: first created by {'-- ZefDB user --'} at ...",
# #f"# last change: by -- ZefDB user -- ...",
# # f'# z_zef_function = g["{uid(z_zef_function)}"]["{uid(z_zef_function | ops.frame)}"]',            # TODO: update this to new uid and ref frame syntax
# f'# Original function name: {original_fct_name}' if original_fct_name is not None else None,
# f"g = Graph('{uid(g)}')     # This zef function lives on this graph tagged with {g.tags}'",
# f'@func(g = g,',
# f"    label = '{value(z_zef_function >> RT.Label)}'," if z_zef_function | ops.has_out[RT.Label] | collect else None,
# f"    is_pure = {value(z_zef_function >> RT.IsPure)}," if z_zef_function | ops.has_out[RT.IsPure] | collect else None,
# *[f"    {value(z_ed>>RT.Name)} = g['{uid(z_ed | target)}'] | to_frame[g['{value(z_ed>>RT.UseTimeSlice)}']]," for z_ed in (z_zef_function > ops.L[RT.Binding] | collect) ],
# f")\n"
#         ] | ops.filter[lambda x: x is not None] | collect
#         )
    
#     def _generate_zef_fct_str(self, z_zef_function: ZefRef):  
#         from zefdb.ops import collect, value
#         z_str = z_zef_function >> RT.PythonSourceCode | collect
#         assert AET(z_str) == AET.String        
#         return self._make_header(z_zef_function) + (value(z_str))
    
#     def __call__(self, z_zef_function: Union[ZefRef, ZefRefs]):
#         if isinstance(z_zef_function, str):
#             pyperclip.copy(z_zef_function)
#             return z_zef_function
        
#         assert isinstance(z_zef_function, ZefRef) or isinstance(z_zef_function, ZefRefs)
#         z_zef_functions = [z_zef_function] if isinstance(z_zef_function, ZefRef) else z_zef_function        
#         pyperclip.copy('#%%' + '\n'*10 + ("\n"*5).join([self._generate_zef_fct_str(z_fct) for z_fct in z_zef_functions]))   # copy to clipboard
#         return z_zef_function       # allow piping through
    
#     def __ror__(self, z_zef_function):
#         return self(z_zef_function)
    

# #to be used with one ZefRef or ZefRefs to ET.ZEF_Function
# to_clipboard = ToClipboard()


from .fx_types import Effect
from ..error import Error


def clipboard_copy_to_handler(eff: dict):
    """ 
    sample effect:
    {
        'type': FX.Clipboard.CopyTo,
        'content': 'hello',
    }
    """    
    try:
        import pyperclip
    except:
        err = """
        please install pyperclip if you want to use the copy to/from
        clipboard functionality. E.g. 'pip3 install pyperclip'
        """
        raise RuntimeError(err)
    try:
        val = eff['content']
        if type(val) in {str, float, int, bool}:
            pyperclip.copy(str(val))
        else:
            raise RuntimeError(f"copying a type type(val)={type(val)} to the clipboard is not supported. Value: {val}")
        return {}
    except Exception as e:
        return Error(f'executing FX.Clipboard.CopyTo for effect {eff}:\n{repr(e)}')





def clipboard_copy_from_handler(eff: dict):
    """ 
    Get the content from the OS's clipboard. This is returned 
    in the dictionary as the value associated with the 'content'
    key.

    ---- Examples ----
    >>> {
            'type': FX.Clipboard.CopyFrom,            
        }
    """

    try:
        import pyperclip
    except:
        err = """
        please install pyperclip if you want to use the copy to/from
        clipboard functionality. E.g. 'pip3 install pyperclip'
        """
        raise RuntimeError(err)

    try:
        val = pyperclip.paste()
        return {'content': val}
    except Exception as e:
        return Error(f'executing FX.Clipboard.CopyFrom for effect {eff}:\n{repr(e)}')


