"""
    Copyright 2016 Inmanta

    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.

    Contact: code@inmanta.com
"""

typedef uuid as string matching /[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}/

implementation none for std::Entity:

end

entity ManagedDevice:
    """
        This interface represents all devices that can be managed
    """
    hoststring  name
end

entity Host extends ManagedDevice:
    """
        A host models a server of computer in the managed infrastructure
    """
end

implement Host using hostDefaults

index Host(name)

typedef hoststring as string matching /^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*$/

entity File:
    """
        This represents a file on the filesystem

        :param path The path of the file
        :param mode The permissions of the file
        :param owner The owner of the file
        :param group The group of the file
        :param content The file contents
        :param reload If a service requires this file, reload or restart
            the service when this file changes.
    """
    string  path
    number  mode
    string  owner
    string  group
    string  content
    bool    reload = false
    bool    purged = false
end

implement File using std::none

typedef ConfigFile as File(mode = 644, owner = "root", group = "root")

Host host [1] -- [0:] File files

index File(host, path)

# the state of a service
typedef service_state as string matching self == "running" or self == "stopped"

# a service that is managed
entity Service:
    string          name
    service_state   state
    bool            onboot
    bool            reload = false
end

implement Service using std::none

Host host [1] -- [0:] Service services

index Service(host, name)

# the state of a package
typedef package_state as string matching self == "installed" or
                                         self == "removed" or self == "latest"

entity Package:
    """
        A software package installed on a managed device.
    """
    string          name
    package_state   state
    bool            reload = false
end

implement Package using std::none

Host host [1] -- [0:] Package packages

index Package(host, name)

entity Directory:
    """
        A directory on the filesystem
    """
    string  path
    number  mode
    string  owner
    string  group
    bool    reload = false
    bool    purged = false
end

implement Directory using std::none

typedef DefaultDirectory as Directory(mode = 755, owner = "root", group = "root")

Host host [1] -- [0:] Directory directories

index Directory(host, path)

entity Symlink:
    """
        A symbolic link on the filesystem
    """
    string  source
    string  target
    bool    purged = false
    bool    reload = false
end

implement Symlink using std::none

Host host [1] -- [0:] Symlink symlinks

# define operating systems
unix = OS(name = "unix")
windows = OS(name = "windows")

linux = OS(name = "linux", family = unix)
solaris = OS(name = "solaris", family = unix)
freebsd = OS(name = "freebsd", family = unix)
openbsd = OS(name = "openbsd", family = unix)
macos = OS(name = "macos", family = unix)

entity OS:
    """
        Defines an operating system
    """
    string name
    number version = 0
end

implement OS using std::none

OS os [1] -- [0:] Host host
OS member [0:] -- [0:1] OS family

entity HostConfig:
    """
        This represents generic configuration for a host. This entity is used
        by other modules to include their host specific configuration. This
        should be instantiated in the implementation of std::Host or subclasses.
        This host specific configuration cannot be included by just implementing
        std::Host because possibly subclasses of std::Host are instantiated and
        implementations are not inherited.
    """
end

Host host [1] -- [1] HostConfig host_config
implement HostConfig using std::none

# deps:
# Package   requires Service    when Package.host   == Service.host
# File      requires Service    when File.host      == Service.host
# Directory requires File       when Directory.host == File.host
# Package   requires File       when Package.host   == File.host

implementation hostDefaults for std::Host:
    HostConfig(host = self)
end

entity State:
    """
        Baseclass for entities that contain state

        :param allow_snapshot Allow a snapshot of the state contained in this entity
        :param allow_restore Allow a restore of the state containted in this entity
        :param state_id The id to identify the state. If left empty, the resource id is used.
                        (This can be used for cross environment/model restores)
    """
    bool allow_snapshot = true
    bool allow_restore = true
    string state_id = ""
end

entity HostGroup:
    """
        This entity represents a group of hosts. For example a cluster of machines.
    """
    string name
end

std::Host hosts [0:] -- [0:] HostGroup host_groups

implement HostGroup using std::none
