#!/usr/bin/python3

import re
import sys
import time
import requests
import subprocess
from pathlib import PosixPath
from pathlib import Path

from hook_invoker_lib.hook import template_parser, print_err
from hook_invoker_lib.hook import srv_link, args_volume_type_paser

bin_systemctl = '/bin/systemctl'
_srv_path = '/srv'
_etc_systemd_dir = '/etc/systemd/system/'

SRV_MS = 'ms'
SRV_MSP = 'msp'
SRV_MSR = 'msr'
SRV_MST = 'mst'

services = {
    SRV_MS:      ['ms.service'],
    SRV_MSP:     ['msp.service'],
    SRV_MSR:     ['msr.service'],
    SRV_MST:     ['mst.service'],
}

def Service(name):
    if name in services:
        return SystemController(name)
    else:
        return None

class SystemController:
    def __init__(self, name):
        self._service = name

    @property
    def _service_list(self):
        return services[self._service]

    @property
    def is_systemd_enabled(self):
        return subprocess.call([bin_systemctl, 'is-enabled', '-q', self._service_list[0]], stdout=subprocess.DEVNULL) == 0

    @property
    def need_care(self):
        return self.is_masked or self.is_systemd_enabled

    @property
    def is_active(self):
        return subprocess.call([bin_systemctl, 'status', self._service_list[0]], stdout=subprocess.DEVNULL) == 0

    @property
    def is_inactive(self):
        return subprocess.call([bin_systemctl, 'status', self._service_list[0]], stdout=subprocess.DEVNULL) != 0

    def _condition_srv_gen(self, srv):
        service_dir = PosixPath(_etc_systemd_dir, '{}.d'.format(srv))
        config_path = PosixPath(service_dir, 'condition-srv.conf')

        if not config_path.is_file():
            try:
                service_dir.mkdir(parents=True, exist_ok=True)
                condition_srv = '[Unit]\nConditionPathIsSymbolicLink={}\n'.format(_srv_path)
                config_path.write_text(condition_srv)
            except:
                return False
        return True

    def _condition_srv_del(self, srv):
        service_dir = PosixPath(_etc_systemd_dir, '{}.d'.format(srv))
        config_path = PosixPath(service_dir, 'condition-srv.conf')

        if config_path.is_file():
            try:
                config_path.unlink()
            except:
                print('Failed to unlink file: {}'.format(config_path), file=sys.stderr)
                return False
        return True

    @property
    def _mask_flag(self):
        return Path('/tmp/.mask_{}'.format(self._service))

    @property
    def is_masked(self):
        return self._mask_flag.exists()

    def mask(self):
        try:
            self._mask_flag.write_text('')
        except:
            pass
        return 0 == subprocess.call([bin_systemctl, 'mask', self._service_list[0]], stdout=subprocess.DEVNULL, timeout=10)

    def stop(self):
        return 0 == subprocess.call([bin_systemctl, 'stop', self._service_list[0]], stdout=subprocess.DEVNULL, timeout=210)

    def start(self):
        return 0 == subprocess.call([bin_systemctl, 'start', self._service_list[0]], stdout=subprocess.DEVNULL, timeout=210)

    def unmask(self):
        try:
            self._mask_flag.unlink()
        except:
            pass
        return 0 == subprocess.call([bin_systemctl, 'unmask', self._service_list[0]], stdout=subprocess.DEVNULL, timeout=10)

    def restart(self):
        subprocess.call([bin_systemctl, 'stop', self._service_list[0]], stdout=subprocess.DEVNULL, timeout=210)
        return 0 == subprocess.call([bin_systemctl, 'start', self._service_list[0]], stdout=subprocess.DEVNULL, timeout=210)

    def condition_gen(self):
        ret = all(self._condition_srv_gen(s) for s in self._service_list)
        subprocess.call([bin_systemctl, 'daemon-reload'], stdout=subprocess.DEVNULL, timeout=10)
        return ret

    def condition_del(self):
        ret = all(self._condition_srv_del(s) for s in self._service_list)
        subprocess.call([bin_systemctl, 'daemon-reload'], stdout=subprocess.DEVNULL, timeout=10)
        return ret

if __name__ == "__main__":
    name = template_parser()
    if name is None:
        print_err('not supported template call {}'.format(name))
        sys.exit(1)

    exist, target_path = srv_link()
    volumes, _ = args_volume_type_paser()
    need_handle = any(re.match(r'^\{}\/'.format(volume), target_path) for volume in volumes) if target_path is not None else False
    if not exist or target_path is None or not need_handle:
        print_err('only run when srv link and target exist')
        sys.exit(1)

    service = Service(name)
    if service is None:
        sys.exit(0)

    if not service.need_care:
        print('skip not enabled service {}'.format(name))
        sys.exit(0)

    print('Stop {} service'.format(name))
    try:
        if not service.mask():
            print_err('mask {} failed'.format(name))
            sys.exit(2)

        if service.is_inactive:
            sys.exit(0)

        if not service.stop():
            print_err('stop {} failed'.format(name))
            sys.exit(2)
    finally:
        pass

    time.sleep(0.25)
    sys.exit(0)
