import os
import shutil
from app_launch import RezApplication, WebLinkApplication
import utils_malware
import utils


class BaseMayaApp(RezApplication):
    order = 0
    icon = ":mayaico_2018.png"
    shortcut_icon = "maya_2018.ico"
    name = "maya_2018"
    label = "Maya 2018"
    executable_name = "maya.exe"
    search_list = ["c:/Program Files/Autodesk/Maya2018/bin/maya.exe"]
    #rez-context query
    
    external = True
    extension = ['ma', 'mb']

    def pre_launch_hook(self):
        if utils.get_maya_scan_malware():
            malware_list = utils_malware.scan_for_maya_malware()
            if len(malware_list) > 0:
                result = utils_malware.ask_for_fix_maya_malware(malware_list)
                if result is True:
                    utils_malware.fix_maya_malware(malware_list)

    def environment_hook(self, project, env):
        if utils.get_override_maya_app_dir_var():
            path = utils.get_maya_app_dir_var()
            if path:
                path = os.path.realpath(path)
                env["MAYA_APP_DIR"] = str(path)
                self.log.info("MAYA_APP_DIR has been overrided to {}".format(path))
            else:
                self.log.warning("MAYA_APP_DIR override path not specified. Used standard MAYA_APP_DIR location")
            
class Maya2018App(BaseMayaApp):
    search_list = ["c:/Program Files/Autodesk/Maya2018/bin/maya.exe"]
    name = "maya_2018"
    label = "Maya 2018"
    rez_packages = ["maya-2018"]

class Maya2022App(BaseMayaApp):
    search_list = ["c:/Program Files/Autodesk/Maya2022/bin/maya.exe"]
    name = "maya_2022"
    label = "Maya 2022"
    rez_packages = ["maya-2022"]


class Maya2023App(BaseMayaApp):
    search_list = ["c:/Program Files/Autodesk/Maya2023/bin/maya.exe"]
    name = "maya_2023"
    label = "Maya 2023"
    rez_packages = ["maya-2023"]

class Maya2024App(BaseMayaApp):
    search_list = ["c:/Program Files/Autodesk/Maya2024/bin/maya.exe"]
    name = "maya_2024"
    label = "Maya 2024"
    rez_packages = ["maya-2024"]


class NukeApp(RezApplication):
    order = 0
    icon = ":nuke.png"
    shortcut_icon = "nuke.ico"
    name = "nuke_12"
    label = "Nuke 12"
    command_arguments = ["--nukex"]
    executable_name = "Nuke12.0.exe"
    search_list = ["c:/Program Files/Nuke12.0v2/Nuke12.0.exe"]
    rez_packages = ["python_common", "python27_pyyaml", "wizartsoft_maya2018", "nuke_scripts"]
    external = True
    show_shell = True
    extension = ['nk']

    def __init__(self, *args, **kwargs):
        super(NukeApp, self).__init__(*args, **kwargs)


class Nuke13App(RezApplication):
    order = 0
    icon = ":nuke.png"
    shortcut_icon = "nuke.ico"
    name = "nuke_13"
    label = "Nuke 13"
    command_arguments = ["--nukex"]
    executable_name = ["Nuke13.0.exe","Nuke13.2.exe"]
    search_list = ["C:/Program Files/Nuke13.0v1/Nuke13.2.exe","C:/Program Files/Nuke13.0v1/Nuke13.0.exe"]
    rez_packages = ["python37_pyyaml", "python_common", "wizartsoft_maya2018", "nuke_scripts"]
    external = True
    show_shell = True
    extension = ['nk']

    def __init__(self, *args, **kwargs):
        super(Nuke13App, self).__init__(*args, **kwargs)


class Nuke15App(RezApplication):
    order = 0
    icon = ":nuke.png"
    shortcut_icon = "nuke.ico"
    name = "nuke_15"
    label = "Nuke 15"
    command_arguments = ["--nukex"]
    executable_name = ["Nuke15.0.exe"]
    search_list = []
    rez_packages = ["nuke-15"]
    external = True
    show_shell = True
    extension = ['nk']

    def __init__(self, *args, **kwargs):
        super(Nuke15App, self).__init__(*args, **kwargs)

class Katana6App(RezApplication):
    order = 0
    name = "katana_6"
    label = "Katana 6"
    executable_name = ["katanaBin.exe"]
    search_list = ["d:/Program Files/Katana6.0v1/bin/katanaBin.exe"]
    rez_packages = ["katana-6.0"]
    external = True
    show_shell = True
    extension = ['katana']

    def __init__(self, *args, **kwargs):
        super(Katana6App, self).__init__(*args, **kwargs)


class Houdini175App(RezApplication):
    order = 0
    icon = ":houdini.png"
    shortcut_icon = "houdini.ico"
    name = "houdini_17.5"
    label = "Houdini 17.5"
    executable_name = "houdinifx.exe"
    search_list = []
    rez_packages = ["usd_houdini_embedded-17.5", "wizart_houdini_farm", "houdini-17.5"]
    external = True
    show_shell = True
    def __init__(self, *args, **kwargs):
        super(Houdini175App, self).__init__(*args, **kwargs)


class Houdini18App(RezApplication):
    order = 0
    icon = ":houdini.png"
    shortcut_icon = "houdini.ico"
    name = "houdini_18.0"
    label = "Houdini 18.0"
    executable_name = "houdinifx.exe"
    search_list = []
    rez_packages = ["wizart_houdini_farm", "houdini-18.0"]
    external = True
    show_shell = True
    redirect_output = False
    def __init__(self, *args, **kwargs):
        super(Houdini18App, self).__init__(*args, **kwargs)


class AdobeSubstance3DPainter(RezApplication):
    order = 15
    icon = ':adobeSP.png'
    shortcut_icon = "adobeSP.ico"
    name = 'substance_painter'
    label = 'Adobe Substance 3D Painter'
    executable_name = 'Adobe Substance 3D Painter.exe'
    search_list = ['C:/Program Files/Adobe/Adobe Substance 3D Painter/Adobe Substance 3D Painter.exe']
    rez_packages = ['wizart_publish']
    external = True
    show_shell = False
    redirect_output = True

    def __init__(self, *args, **kwargs):
        super(AdobeSubstance3DPainter, self).__init__(*args, **kwargs)


class DaVinciResolve17(RezApplication):
    order = 0
    icon = ':davinci17.png'
    shortcut_icon = 'davinci17.ico'
    name = 'davinci_resolve_17'
    label = 'DaVinci Resolve 17'
    executable_name = 'Resolve.exe'
    search_list = []
    rez_packages = ['davinci_resolve', 'resolve_scripts', 'otio', 'otio_wref', 'wref_resolver', 'boost-1.70']
    external = True
    show_shell = False
    redirect_output = True

    def __init__(self, *args, **kwargs):
        super(DaVinciResolve17, self).__init__(*args, **kwargs)
    
    def start_arguments_hook(self, env, executable_cmd):
            DAVINCI_RESOLVE_EXTENSIONS_COPY_LIST = env.get("DAVINCI_RESOLVE_EXTENSIONS_COPY_LIST")
            if DAVINCI_RESOLVE_EXTENSIONS_COPY_LIST:
                davinci_ext_folder = os.path.expandvars("$PROGRAMDATA/Blackmagic Design/DaVinci Resolve/Fusion/Scripts/Edit")
                if not os.path.exists(davinci_ext_folder):
                    os.makedirs(davinci_ext_folder)
                for extension_path in DAVINCI_RESOLVE_EXTENSIONS_COPY_LIST.split(';'):
                    extension_file_name = os.path.basename(extension_path)#
                    dst_path = os.path.join(davinci_ext_folder, extension_file_name)
                    try:
                        shutil.copyfile(extension_path, dst_path)
                        self.log.info('DaVinci Resolve Extension copy file from "{}" to "{}"'.format(extension_path, dst_path))
                    except IOError:
                        self.log.warning('DaVinci Resolve Extension failed copy file "{}" to "{}"'.format(extension_path, dst_path))
            return [executable_cmd]



class Houdini185App(RezApplication):
    order = 0
    icon = ":houdini.png"
    shortcut_icon = "houdini.ico"
    name = "houdini_18.5"
    label = "Houdini 18.5"
    executable_name = "houdinifx.exe"
    search_list = []
    rez_packages = ["houdini-18.5"]
    external = True
    show_shell = False
    redirect_output = True
    def __init__(self, *args, **kwargs):
        super(Houdini185App, self).__init__(*args, **kwargs)


class Houdini190App(RezApplication):
    order = 0
    icon = ":houdini.png"
    shortcut_icon = "houdini.ico"
    name = "houdini_19.0"
    label = "Houdini 19.0"
    executable_name = "houdinifx.exe"
    search_list = []
    rez_packages = ["houdini-19.0"]
    external = True
    show_shell = False
    redirect_output = True
    def __init__(self, *args, **kwargs):
        super(Houdini190App, self).__init__(*args, **kwargs)

class Houdini195App(RezApplication):
    order = 0
    icon = ":houdini.png"
    shortcut_icon = "houdini.ico"
    name = "houdini_19.5"
    label = "Houdini 19.5"
    executable_name = "houdinifx.exe"
    search_list = []
    rez_packages = ["houdini-19.5"]
    external = True
    show_shell = True
    redirect_output = False
    def __init__(self, *args, **kwargs):
        super(Houdini195App, self).__init__(*args, **kwargs)

class Houdini200App(RezApplication):
    order = 0
    icon = ":houdini.png"
    shortcut_icon = "houdini.ico"
    name = "houdini_20.0"
    label = "Houdini 20.0"
    executable_name = "houdinifx.exe"
    search_list = []
    rez_packages = ["houdini-20.0"]
    external = True
    show_shell = True
    redirect_output = False
    def __init__(self, *args, **kwargs):
        super(Houdini200App, self).__init__(*args, **kwargs)


class Houdini205App(RezApplication):
    order = 0
    icon = ":houdini.png"
    shortcut_icon = "houdini.ico"
    name = "houdini_20.5"
    label = "Houdini 20.5"
    executable_name = "houdinifx.exe"
    search_list = []
    rez_packages = ["houdini-20.5"]
    external = True
    show_shell = True
    redirect_output = False
    def __init__(self, *args, **kwargs):
        super(Houdini205App, self).__init__(*args, **kwargs)


class WizartBuildHoudini195(RezApplication):
    """
    Special version of Houdini with swapped HoudiniUsdBridge
    """
    order = 40
    icon = ":houdini.png"
    shortcut_icon = "houdini.ico"
    name = "wizart_houdini_19.5"
    label = "Houdini 19.5 (Wizart Build)"
    command = "%WIZART_BUILD_HFS%/bin/houdinifx.exe"
    show_shell = True
    redirect_output = False
    #rez-context query
    rez_packages = ["wizart_build_houdini-19.5"]
    external = False
    extension = ["hip"]

class Vegas16App(RezApplication):
    order = 15
    name = "vegas_16"
    icon = ":vegas.png"
    shortcut_icon = "vegas.ico"
    label = "Sony Vegas 16.0"
    executable_name = "vegas160.exe"
    search_list = ["C:/Program Files/VEGAS/VEGAS Pro 16.0/vegas160.exe"]
    rez_packages = ["vegas-16.0", "python-3.7", "vegas_python", "wizart_dcc_PySide2", "qt", "python_common", "wizart_publish", "otio", "wref_resolver", "boost-1.73", "fs_ctrl", "wizart_desktop", "prodtrack_api", "assetvcs_api"]
    external = True
    show_shell = False
    redirect_output = True
    
    def __init__(self, *args, **kwargs):
        super(Vegas16App, self).__init__(*args, **kwargs)
    
    def start_arguments_hook(self, env, executable_cmd):
        SONY_VEGAS_EXTENSIONS_COPY_LIST = env.get("SONY_VEGAS_EXTENSIONS_COPY_LIST")
        if SONY_VEGAS_EXTENSIONS_COPY_LIST:
            vegas_ext_folder = os.path.expanduser("~/Documents/Vegas Application Extensions")
            if not os.path.exists(vegas_ext_folder):
                os.makedirs(vegas_ext_folder)
            for src_assembly_path in SONY_VEGAS_EXTENSIONS_COPY_LIST.split(';'):
                assembly_file_name = os.path.basename(src_assembly_path)
                dst_assembly_path = os.path.join(vegas_ext_folder, assembly_file_name)
                try:
                    shutil.copyfile(src_assembly_path, dst_assembly_path)
                    self.log.info('Vegas Extension copy file from "{}" to "{}"'.format(src_assembly_path, dst_assembly_path))
                except IOError:
                    self.log.warning('Vegas Extension failed copy file "{}" to "{}"'.format(src_assembly_path, dst_assembly_path))
        
        SONY_VEGAS_RENDER_TEMPLATES_COPY_LIST = env.get("SONY_VEGAS_RENDER_TEMPLATES_COPY_LIST")
        if SONY_VEGAS_RENDER_TEMPLATES_COPY_LIST:
            vegas_render_templates_folder = os.path.expanduser("~/AppData/Roaming/VEGAS/Render Templates/avc")
            if not os.path.exists(vegas_render_templates_folder):
                os.makedirs(vegas_render_templates_folder)
            for src_path in SONY_VEGAS_RENDER_TEMPLATES_COPY_LIST.split(';'):
                template_name = os.path.basename(src_path)
                template_path = os.path.join(vegas_render_templates_folder, template_name)
                try:
                    shutil.copyfile(src_path, template_path)
                    self.log.info('Vegas Extension copy file from "{}" to "{}"'.format(src_path, template_path))
                except IOError:
                    self.log.warning('Vegas Extension failed copy file "{}" to "{}"'.format(src_path, template_path))
        
        return [executable_cmd]

class BaseMaxApp(object):
    order = 1
    icon = ":max_2018.png"
    shortcut_icon = "max_2018.ico"
    name = "max_2018"
    executable_name = "3dsmax.exe"
    external = True
    search_plugin_in_path_template = "$USERPROFILE/AppData/Local/Autodesk/3dsMax/%(version)d - 64bit/ENU/Plugin.UserSettings.ini"

    @property
    def search_plugin_in_path(self):
        raise NotImplementedError()

    def start_arguments_hook(self, env, executable_cmd):
        """
        All rez packages should modify MAX_REZ_PLUGIN_PATH, then
        we generate temprorary plugin.ini and pass it to max
        using 3dsmax.exe -p plugin_path.ini
        """
        max_startup_script = env.get("MAX_STARTUP_SCRIPT")
        max_startup_args =  ['-U', 'PythonHost', max_startup_script] if max_startup_script else []
        if env.get('MAX_REZ_PLUGIN_PATH'):
            self.log.info("3dsmax plugin hook, found 'MAX_REZ_PLUGIN_PATH'")
            from ConfigParser import SafeConfigParser
            import tempfile
            import codecs
            existing_plugin_ini = os.path.expandvars(self.search_plugin_in_path)
            parser = SafeConfigParser()
            def _is_utf_16(path):
                try:
                    with codecs.open(path, 'r', encoding='utf-16') as f:
                        f.readline()
                    return True
                except UnicodeError:
                    return False
            codec_name = "utf-16" if _is_utf_16(existing_plugin_ini) is True else "ascii"
            with codecs.open(existing_plugin_ini, 'r', encoding=codec_name) as f:
                parser.readfp(f)
            self.log.info("Found user plugin.ini'%s' " % existing_plugin_ini)
            for i, entry in enumerate (env.get('MAX_REZ_PLUGIN_PATH').split(';')):
                generate_name = "MAX_REZ_PLUGIN_PATH_%d" % i
                parser.set('Directories', generate_name, entry)
            handle, plugin_ini_path = tempfile.mkstemp(suffix="_plugin.ini")
            os.close(handle)
            with codecs.open(plugin_ini_path, 'w', encoding=codec_name) as f:
                parser.write(f)
                self.log.info("write temprorary plugin.ini '%s' " % plugin_ini_path)

            return [executable_cmd, '-p', plugin_ini_path] + max_startup_args
        else:
            self.log.info("3dsmax plugin hook, not found 'MAX_REZ_PLUGIN_PATH' in env")
            return [executable_cmd]  + max_startup_args


class Max2018App(BaseMaxApp, RezApplication):
    order = 1
    name = "max_2018"
    label = "3ds Max 2018"
    search_list = ["c:/Program Files/Autodesk/3ds Max 2018/3dsmax.exe"]
    #rez-context query
    rez_packages = ["max-2018", "max_usd_camera_import"]

    def __init__(self, *args, **kwargs):
        super(Max2018App, self).__init__(*args, **kwargs)

    @property
    def search_plugin_in_path(self):
        return self.search_plugin_in_path_template % dict(version=2018)


class Max2019App(BaseMaxApp, RezApplication):
    order = 1
    name = "max_2019"
    label = "3ds Max 2019"
    search_list = ["c:/Program Files/Autodesk/3ds Max 2019/3dsmax.exe"]
    #rez-context query
    rez_packages = ["max-2019", "max_startup", "usd", "usd_outliner", "python_common", "usd_max", "max_usd_camera_import"]

    def __init__(self, *args, **kwargs):
        super(Max2019App, self).__init__(*args, **kwargs)

    @property
    def search_plugin_in_path(self):
        return self.search_plugin_in_path_template % dict(version=2019)


class Max2021App(BaseMaxApp, RezApplication):
    order = 1
    name = "max_2021"
    label = "3ds Max 2021"
    search_list = ["c:/Program Files/Autodesk/3ds Max 2021/3dsmax.exe"]
    #rez-context query
    rez_packages = ["max-2021", "max_startup", "usd", "usd_outliner", "python_common", "usd_max", "max_usd_camera_import"]

    def __init__(self, *args, **kwargs):
        super(Max2021App, self).__init__(*args, **kwargs)

    @property
    def search_plugin_in_path(self):
        return self.search_plugin_in_path_template % dict(version=2021)

class UsdViewApp(RezApplication):
    order = 2
    icon = ":usd.png"
    shortcut_icon = "usd.ico"
    name = "usdview"
    label = "USD View"
    executable_name = "usdview"
    command_default_argument = "%USDVIEW_DEFAULT_USD_FILE%"
    command = "usdview"
    show_shell = False
    redirect_output = True
    #rez-context query
    rez_packages = ["usdview","al_usdmaya","usd_arnold","eye_shader"]
    external = False
    extension = ['usd', 'usda', 'usdc']

class Anim3DPlatformApp(RezApplication):
    order = 3
    icon = ":dcc.png"
    shortcut_icon = "dcc.ico"
    name = "wizart_dcc"
    label = "Anim 3D Platform"
    executable_name = "wizart_dcc"
    command = "%WIZART_DCC_ROOT%/bin/dcc_base.exe"
    show_shell = True
    redirect_output = False
    #rez-context query
    rez_packages = ["wizart_dcc_platform"]
    external = False
    extension = ['usd', 'usda', 'usdc']


class Anim3DPlatformAppSceneLibApp(RezApplication):
    order = 3
    icon = ":dcc.png"
    shortcut_icon = "dcc.ico"
    name = "wizart_dcc_scene_lib"
    label = "Anim 3D Platform (SceneLib)"
    executable_name = "wizart_dcc_scene_lib"
    command = "%WIZART_DCC_ROOT%/bin/dcc_base.exe"
    command_arguments = ["--config", "%WIZART_DCC_ROOT%/configs/scene_lib.toml"]
    show_shell = True
    redirect_output = False
    #rez-context query
    rez_packages = ["wizart_dcc_platform"]
    external = False
    extension = ['usd', 'usda', 'usdc']

class Anim3DPlatformAppBeta(Anim3DPlatformApp):
    """
    Since we don't have better mechanizm, use it for newest tech to try out (other rez packages)
    """
    order = 50
    name = "wizart_dcc_beta"
    label = "Anim 3D Platform (Beta)"

class ProdTrackSyncApp(RezApplication):
    order = 4
    name = "prod_track_sync"
    label = "Prod Track Sync"
    executable_name = "python"
    command = "python"
    command_arguments = ["-m", "prod_track_sync.main"]
    show_shell = False
    redirect_output = True
    #rez-context query
    rez_packages = ["prod_track_sync"]
    external = False

    def is_allowed_for_user_hook(self):
        import auth_session
        data = auth_session.get_prodtrack_user_info()
        return data.get("is_staff", False)


class FreelanceAdminApp(RezApplication):
    order = 5
    name = "freelance_admin"
    label = "Freelance Admin"
    executable_name = "python"
    command = "python"
    command_arguments = ["-m", "freelance_admin.main"]
    show_shell = False
    redirect_output = True
    #rez-context query
    rez_packages = ["freelance_admin"]
    external = False
    def environment_hook(self, project, env):
        """
        Modify environment variables so usd resolver can pick freelance available resources
        """
        if project:
            env["ASSET_PAYLOAD_TYPE"] = "payload_freelance"
            env["SCENE_LAYER_STACK_TYPE"] = "freelance_stack"

class VsCodeApp(RezApplication):
    order = 6
    name = "code"
    icon = ":code.png"
    shortcut_icon = "code.ico"
    label = "VsCode"
    executable_name = "code"
    command = "code"
    command_arguments = ["--extensions-dir", "%VSCODE_PORTABLE_ROOT%/extensions"]
    show_shell = False
    redirect_output = False
    rez_packages = ["vscode","usd","wref_resolver"]
    external = False
    extension = ['py', 'json', 'usd', 'usda', 'usdc']

class PublishApp(RezApplication):
    order = 9
    name = "publish"
    label = "Publish"
    icon = ":pyblish.png"
    executable_name = "python"
    command = "python"
    command_arguments = ["-m", "wizart.publish.standalone"]
    show_shell = False
    redirect_output = True
    rez_packages = ["python-2.7","wizart_dcc_python27_PySide2", "wizart_publish", "python_common", "usd", "wref_resolver", "fs_ctrl", "assetvcs_api", "prodtrack_api", "wizart_desktop"]
    external = False


class SoundPublishApp(RezApplication):
    order = 9
    name = "sound_publish"
    label = "Sound Publish"
    icon = ":pyblish.png"
    executable_name = "python"
    command = "python"
    command_arguments = ["-m", "wizart.publish.sound_publish"]
    show_shell = False
    redirect_output = True
    rez_packages = ["python-2.7","wizart_dcc_python27_PySide2", "wizart_publish", "python_common","wref_resolver", "fs_ctrl", "assetvcs_api","prodtrack_api","wizart_desktop"]
    external = False

class EditorialCutterApp(RezApplication):
    order = 9
    name = "editorial_cutter"
    label = "Editorial Cutter"
    icon = ":pyblish.png"
    executable_name = "python"
    command = "python"
    command_arguments = ["-m", "wizart.publish.editorial_cutter.main"]
    show_shell = True
    redirect_output = False
    rez_packages = ["python-3.7", "wizart_dcc_PySide2", "qt", "wizart_publish", "python_common","wref_resolver", "fs_ctrl", "assetvcs_api","prodtrack_api","wizart_desktop", "otio", "otio_wref", "boost-1.73", "ffmpeg"]
    external = False

class LayoutUsdConverterApp(RezApplication):
    order = 9
    name = "layout_usd_converter"
    label = "Layout Usd Converter"
    icon = ":pyblish.png"
    executable_name = "python"
    command = "python"
    command_arguments = ["-m", "wizart.publish.layout_publish"]
    show_shell = False
    redirect_output = True
    rez_packages = ["python-2.7","wizart_dcc_python27_PySide2", "wizart_publish", "python_common","wref_resolver", "fs_ctrl", "assetvcs_api","prodtrack_api","wizart_desktop", "python27_jinja2", "rez"]
    external = False



class ProdTrackLink(WebLinkApplication):
    order = 10
    #icon generated via https://eu.ui-avatars.com/api/?rounded=true&name=Prod+track&background=0D8ABC&color=fff&bold=true&size=256&uppercase=false
    icon = ":prodtrack.png"
    name = "prodtrack"
    label = "ProdTrack"
    shortcut_icon = "prodtrack.ico"
    url = "https://prodtrack.voronezh.studio/"
    

class AssetBrowserApp(RezApplication):
    order = 11
    name = "asset_browser"
    label = "Asset Browser"
    executable_name = "python"
    command = "python"
    command_arguments = ["-m", "wizart.publish.browser_window"]
    show_shell = False
    redirect_output = True
    rez_packages = ["python-2.7", "wizart_dcc_python27_PySide2", "wizart_publish", "python_common", "python27_psutil", "cef_picker", "wizart_desktop", "prodtrack_api", "assetvcs_api", "fs_ctrl"]
    external = False

class OpenCueGuiApp(RezApplication):
    order = 12
    name = "opencue_cuegui"
    label = "OpenCue Gui"
    executable_name = "python"
    command = "python"
    command_arguments = ["-m", "cuegui"]
    show_shell = False
    redirect_output = True
    rez_packages = ["python-3.7","python37_PySide2", "python37_opencue_api","opencue_cuegui"]
    external = False


class OpenRvApp(RezApplication):
    order = 12
    icon = ":openrv.png"
    shortcut_icon = "openrv.ico"
    name = "openrv"
    label = "Open RV"
    executable_name = "python"
    command = "%REZ_OPENRV_ROOT%/bin/rv.exe"
    command_arguments = []
    show_shell = False
    redirect_output = True
    rez_packages = ["openrv"]
    external = False

def get_apps():
    return sorted([app_class() for app_class in app_launch.Application.__subclasses__()], key = lambda x: x.order)
