@startuml

namespace MellowPlayer.Main {
    class Program {
        + main(): int
        + onInitialized()
        + onStarted()

    }
    Program --> MellowPlayer.Infrastructure.IApplication
    Program --> MellowPlayer.Presentation.IMainWindow
    Program --> MellowPlayer.Presentation.IMprisPlayer
    Program -up-> MellowPlayer.Domain.IPlayers
}

namespace MellowPlayer.Domain {
    interface IPlayers #PaleGreen
}

namespace MellowPlayer.Infrastructure {
    interface IApplication #PaleGreen {
        initialized: signal<void>
        started: signal<bool>
        initialize()
        run()
        quit()
        restart()
    }

    class ApplicationDecorator #PaleGreen {
        + initialized: signal<void>
        + started: signal<bool>
        # _application: IApplication
        + initialize()
        + run()
        + quit()
        + restart()
    }

    IApplication <|.. ApplicationDecorator

    class SingleInstance #PaleGreen {
        + initialize()
        + run()
    }
    ApplicationDecorator <|-- SingleInstance

    class WithCommandLineArguments #PaleGreen {
        + run()
    }
    ApplicationDecorator <|-- WithCommandLineArguments

    class WithLogging #PaleGreen {

    }
    ApplicationDecorator <|-- WithLogging

        interface IQtApplication #PaleGreen {
            setApplicationName(QString value)
            setApplicationDisplayName(QString value)
            setApplicationVersion(QString value)
            setOrganizationDomain(QString value)
            setOrganizationName(QString value)
            setWindowIcon(const QIcon& icon)
            exec()
            exit(int returnCode)
            installTranslator(QTranslator* translator)
            setFont(const QFont& font)
            --signals--
            aboutToQuit
            commitDataRequest
        }
        class QtApplication #PaleGreen {
        }
        IQtApplication <|- QtApplication
}

namespace MellowPlayer.Presentation {
    class Application #PaleGreen {
        + quitRequested: signal<void>
        + requestQuit()
        --
        + initialize()
        + run()
        + quit()
        + restart()
    }
    MellowPlayer.Infrastructure.IApplication <|.. Application
    ContextProperty <|- Application
    Application -> MellowPlayer.Infrastructure.IQtApplication

    interface IQmlApplicationEngine #PaleGreen {
        setContextProperty(QString, QObject*)
        addImportPath(QString)
        load(QUrl)
    }
    class QmlApplicationEngine #PaleGreen {
        - _qQmlApplicationEngine: QQmlApplicationEngine
        + setContextProperty(QString, QObject*)
        + addImportPath(QString)
        + load(QUrl)
    }
    IQmlApplicationEngine <|.. QmlApplicationEngine

    interface IContextProperty #PaleGreen {
        void initialize(IQmlApplicationEngine&)
    }

    class ContextProperty #PaleGreen {
        - name: QString
        - propertyObject: QObject*
        void initialize(IQmlApplicationEngine&)
    }
    IContextProperty <|.. ContextProperty
    ContextProperty .up.> IContextProperties

    interface IContextProperties #PaleGreen {
        add(IContextProperty)
    }

    class ContextProperties #PaleGreen {
        + add(IContextProperty)
    }
    IContextProperties <|.. ContextProperties
    ContextProperties --> IQmlApplicationEngine

    interface IMainWindow #PaleGreen {
        load()
        show()
        hide()
    }

    class MainWindow #PaleGreen {
        + load()
        + show()
        + hide()
    }
    IMainWindow <|.up.. MainWindow
    ContextProperty <|-- MainWindow

    interface IMprisPlayer {
        start()
    }
    class MprisPlayer {
        + start()
    }
    IMprisPlayer <|-- MprisPlayer

    class NullMprisPlayer {
        + start()
    }
    IMprisPlayer <|-- NullMprisPlayer
}


'note bottom
'Refactoring steps:
'
'- [ ] implement new classes
'    - [x] IApplication
'    - [x] ApplicationDecorator
'    - [x] WithLogging
'    - [x] WithCommandLineArguments
'    - [x] Application
'    - [x] IContextProperties
'    - [x] ContextProperties
'    - [x] IContextProperty
'    - [x] ContextProperty
'    - [x] IQtApplication
'    - [x] QtApplication
'    - [x] IMainWindow
'    - [x] MainWindow
'    - [x] IQmlApplicationEngine
'    - [x] QmlApplicationEngine
'    - [x] SingleInstance
'
'- [ ] bind IContextProperties and use them in all existing context properties, remove registration in MainWindowViewModel
'
'- [ ] Copy some classes from infrastructure to presentation (and rename old one with a Deprecated prefix) and make them use IMainWindow instead of IDeprecatedMainWindow
'    - [ ] Hotkeys
'    - [ ] Mpris
'- [ ] bind IApplication to a fully decorated instance
'- [ ] Create Program class and use it in main
'- [ ] Delete all deprecated classes, the application should now work as before but with a brand new internal design :-)
'- [ ] Improve SingleInstance to fix some issues appearing sometime on linux (initial issue that motivated this refactoring)
'
'
'end note

@enduml
