@startuml

namespace MellowPlayer.Domain {
    interface IPluginVisitor {
        visit(WebPlayerPlugin&)
        visit(NativePlayerPlugin&)
    }

    interface IPlayerPlugins {
        load(): void
        toList(): QList<IPlayerPlugins>
    }

    class PlayerPlugins {
        # _list: QList<IPlayerPlugins>
        + {abstract} load()
        + toList(): QList<IPlayerPlugins>
    }
    IPlayerPlugins <|-- PlayerPlugins
    PlayerPlugins -> IPlayerPlugin

    class PluginMetadata {
        + author: QString
        + authorUrl: QString
        + logo: QString
        + name: QString
        + version: QString
        + {abstract} load(): void
    }

    interface IPlugin {
        isEnabled: bool
        metadata: PluginMetadata
        path: QString
        load(): void
        accept(IPluginVisitor& visitor)
    }
    IPlugin -up-> PluginMetadata
    IPlugin .up.> IPluginVisitor: <<use>>

    interface IPlayerPlugin {
        player: IPlayer
    }
    IPlugin <|.. IPlayerPlugin

    class WebPlayerPlugin {
        + {abstract} load(): void
        + script: WebPlayerScript
        + url: QString
        + accept(IPluginVisitor& visitor)

    }
    IPlayerPlugin <|.. WebPlayerPlugin

    class WebPlayerScript {
        + code: QString
        + constants: QString
        + isValid(): bool
        + update(): QString
        + play(): QString
        + pause(): QString
        + next(): QString
        + previous(): QString
        + setVolume(double volume): QString
        + addToFavorites(): QString
        + removeFromFavorites(): QString
        + seekToPosition(double position): QString
        + {abstract} load(): void
    }
    WebPlayerPlugin -right-> WebPlayerScript

    class NativePlayerPlugin {
        + {abstract} load(): void
        + accept(IPluginVisitor& visitor)
    }
    IPlayerPlugin <|.. NativePlayerPlugin
}

namespace MellowPlayer::Infrastructure {
    class PlayerPlugins {
        + load(): void
    }
    MellowPlayer.Domain.PlayerPlugins <|-- PlayerPlugins

    class WebPlayerPlugin {
        + load(): void
    }
    MellowPlayer.Domain.WebPlayerPlugin <|-- WebPlayerPlugin

    class NativePlayerPlugin {
        + load(): void
    }
    MellowPlayer.Domain.NativePlayerPlugin <|-- NativePlayerPlugin

    class WebPlayerScript {
        + load(): void
    }
    MellowPlayer.Domain.WebPlayerScript <|-- WebPlayerScript

    class PluginMetadata {
        + load(): void
    }
    MellowPlayer.Domain.PluginMetadata <|-- PluginMetadata

    interface IFile {
        path(): QString
        exists(): bool
        content(): QString
        setContent(QString)
        contentChanged()
    }
    class TextFile
    IFile <|.. TextFile

    interface IIniFile {
         value(const QString& key): QVariant
    }

    class IniFile
    IIniFile <|.. IniFile
    IniFile -> IFile

    class FileDecorator
    IFile <|.. FileDecorator

    class Watched
    FileDecorator <|-- Watched

    interface IFileFactory {
        create(QString path): IFile
    }
    IFileFactory ..> IFile: <<create>>

    interface IIniFileFactory {
        create(QString path): IFile
    }
    IIniFileFactory ..> IIniFile: <<create>>

    WebPlayerScript ..> IFile: <<use>>
    PluginMetadata ..> IIniFile: <<use>>
    WebPlayerPlugin ..> IFileFactory: <<use>>
    WebPlayerPlugin ..> IIniFileFactory: <<use>>
}

@enduml
