#!/usr/bin/env python
# Copyright (C) 2012-2013  Peter Hatina <phatina@redhat.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.

import os
import sys

from lmi.lmi_options import LmiBasicOptions
from lmi.lmi_address import LmiIpv4Addr, LmiHostGenerator
from lmi.lmi_client_ip import LmiIpClient

class LmiIpOptions(LmiBasicOptions):
    OBJ_UNKNOWN, OBJ_ADDR, OBJ_ROUTE = range(3)
    OP_UNKNOWN, OP_SHOW, OP_SET, OP_DEL = range(4)

    def __init__(self):
        super(self.__class__, self).__init__(
            "Available actions:\n"
            "  addr show\n"
            "  addr show [interface]\n"
            "  addr set [address] dev [interface]\n"
            "  addr del dev [interface]\n")
        self._parser.set_usage("Usage: %prog [options] object [command] (dev [device])")
        self._good = True
        self._operation = LmiIpOptions.OP_UNKNOWN
        self._object = LmiIpOptions.OBJ_UNKNOWN
        self._device = ""
        self._ifaddr = ""

    @property
    def good(self):
        return self._good

    @property
    def object(self):
        return self._object

    @property
    def operation(self):
        return self._operation

    @property
    def ifaddr(self):
        return self._ifaddr

    @property
    def device(self):
        return self._device

    def __pos_options_pop_front(self):
        if len(self._pos_options):
            return self._pos_options.pop(0)
        return ""

    def __parse_dev(self):
        arg = self.__pos_options_pop_front()
        if not arg or arg != "dev":
            self._good = False
            return
        self._device = self.__pos_options_pop_front()
        if not self._device:
            self._good = False

    def __parse_op_with_ifaddr(self):
        self._ifaddr = self.__pos_options_pop_front()
        if not self._ifaddr:
           self._good = False
           return
        self.__parse_dev()

    def __parse_op_show(self):
        self._operation = LmiIpOptions.OP_SHOW
        arg = self._pos_options[0] if len(self._pos_options) else ""
        if arg:
            self.__parse_dev()

    def __parse_op_set(self):
        self._operation = LmiIpOptions.OP_SET
        self.__parse_op_with_ifaddr()

    def __parse_op_del(self):
        self._operation = LmiIpOptions.OP_DEL
        self.__parse_dev()

    def __parse_addr(self):
        self._object = LmiIpOptions.OBJ_ADDR
        arg = self.__pos_options_pop_front()
        if arg == "show":
            self.__parse_op_show()
        elif arg == "set":
            self.__parse_op_set()
        elif arg == "del":
            self.__parse_op_del()
        else:
            self._operation = LmiIpOptions.OP_UNKNOWN
            self._good = False

    def __parse_route(self):
        self._object = LmiIpOptions.OBJ_ROUTE

    def parse_cmds(self):
        arg = self.__pos_options_pop_front()
        if arg == "addr":
            self.__parse_addr()
        elif arg == "route":
            self.__parse_route()
        else:
            self._good = False

if __name__ == "__main__":
    options = LmiIpOptions()
    options.parse(sys.argv)
    if not options.good:
        options.print_wrong_usage()
        sys.exit(1)
    options.parse_cmds()
    if not options.good:
        options.print_wrong_usage()
        sys.exit(1)

    client_failed = False
    client_hostnames = LmiHostGenerator.enumerate(options.hostname)
    for client_hostname in client_hostnames:
        if not client_hostname:
            continue
        client = LmiIpClient(client_hostname.name, options.username, options.password)
        rval = True
        errorstr = ""
        if options.object == LmiIpOptions.OBJ_ADDR:
            if options.operation == LmiIpOptions.OP_SHOW:
                if options.device:
                    (rval, _, errorstr) = client.ip_list_devices(options.device)
                else:
                    (rval, _, errorstr) = client.ip_list_devices()
            elif options.operation == LmiIpOptions.OP_SET:
                (rval, _, errorstr) = client.ip_set_address(options.device, options.ifaddr)
            elif options.operation == LmiIpOptions.OP_DEL:
                (rval, _, errorstr) = client.ip_del_address(options.device)
        elif options.object == LmiIpOptions.OBJ_ROUTE:
            # TODO: implement
            sys.stderr.write("Route operation not implemented yet!\n")
            sys.exit(1)
        else:
            sys.stderr.write("Unknown object specified\n")

        if rval:
            sys.stdout.write("%s: %s\n" % (client_hostname.name, errorstr if errorstr else "ok"))
        else:
            sys.stderr.write("%s: %s\n" % (client_hostname.name, errorstr))
            client_failed = True

    sys.exit(client_failed)
