#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
# conditions defined in the file COPYING, which is part of this source code package.

import re
import socket
import sys


def parse_response(data):
    try:
        parsed = dict([x.split("=") for x in data.split(";")][:-1])
        response_type = parsed["type"]
    except (ValueError, KeyError):
        sys.stdout.write("Invalid data: %s\n" % data)
        sys.exit(3)

    if response_type == "1":
        sys.stdout.write("Invalid response: %s\n" % data)
        sys.exit(3)
    return parsed


def send_and_receive(sock, request_str):
    encoding = "utf-8"
    sock.send(request_str.encode(encoding))
    answer = sock.recv(1024)
    return parse_response(answer.decode(encoding))


def check_job(job, s, sid, street, street_nr, city, regex):
    if job == "VERSION":
        sendstring = "version:session=" + sid + "\n"
        data = send_and_receive(s, sendstring)
        try:
            version = data["version_str"]
        except KeyError:
            return 3, "Unknown version"
        return 0, "Version: %s" % version

    if job == "ADDRESS":
        sendstring = (
            "exec:session=%s;request_type=check_address;in_str=%s;in_hno=%s;in_city=%s\n"
            % (
                sid,
                street,
                street_nr,
                city,
            )
        )
        _data = send_and_receive(s, sendstring)

        sendstring = "fetch:session=" + sid + ";out_zip=?;out_city=?\n"
        data = send_and_receive(s, sendstring)

        try:
            city_zip = data["out_zip"]
            city_name = data["out_city"]
        except KeyError:
            return 3, "Unknown zip or city"

        state = 0
        infotext = "Address: %s %s" % (city_zip, city_name)
        if not re.match(regex, data["out_city"]):
            infotext += " but expects %s" % regex
            state = 2

        return state, infotext

    return 3, "Unknown job"


def parse_arguments(sys_args):
    if sys_args is None:
        sys_args = sys.argv[1:]

    host = None
    tcp_port = None
    service = None
    job = None
    street = None
    street_nr = None
    city = None
    regex = None
    try:
        host = sys_args[0]
        tcp_port = int(sys_args[1])
        service = sys_args[2]
        job = sys_args[3]
        if job == "ADDRESS":
            street = sys_args[4]
            street_nr = sys_args[5]
            city = sys_args[6]
            regex = sys_args[7]
    except (IndexError, ValueError):
        sys.stdout.write(
            " Usage: check_uniserv HOSTNAME PORT SERVICE (VERSION|ADDRESS STREET NR CITY SEARCH_REGEX)\n"
        )
        sys.exit(3)

    return host, tcp_port, service, job, street, street_nr, city, regex


def main(sys_args=None):

    host, tcp_port, service, job, street, street_nr, city, regex = parse_arguments(sys_args)

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, tcp_port))

    sendstring = "open:service=" + service + ";servicehost=" + host + "\n"
    data = send_and_receive(s, sendstring)
    sid = data.get("session")
    if not sid:
        return 3, "Error getting SID. Response was: %s\n" % data

    state, infotext = check_job(job, s, sid, street, street_nr, city, regex)

    s.send("close:session=" + sid + "\n")
    s.close()

    return state, "%s\n" % infotext


if __name__ == "__main__":
    exitcode, info = main()
    sys.stdout.write("%s\n" % info)
    sys.exit(exitcode)
