# -*- coding: utf-8 -*-
#
# This file is part of Karesansui.
#
# Copyright (C) 2009 HDE, Inc.
#
# 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.
#

import time
import re

import web

from karesansui.gadget.hostby1firewallrule import validates_rule
from karesansui.lib.rest import Rest, auth
from karesansui.lib.firewall.iptables import KaresansuiIpTables
from karesansui.lib.checker import Checker, \
     CHECK_EMPTY, CHECK_VALID, CHECK_LENGTH, CHECK_CHAR, \
     CHECK_MIN, CHECK_MAX
from karesansui.lib.const import \
     ID_MIN_LENGTH, ID_MAX_LENGTH


from karesansui.lib.utils import get_ifconfig_info

def validates_param_id(obj, rule_id):
    checker = Checker()
    check = True

    _ = obj._
    checker.errors = []

    check = checker.check_number(
            _('Firewall Rule ID'),
            rule_id,
            CHECK_EMPTY | CHECK_VALID | CHECK_MIN | CHECK_MAX,
            min = ID_MIN_LENGTH,
            max = ID_MAX_LENGTH,
        ) and check

    obj.view.alert = checker.errors

    return check
     
class HostBy1FirewallRuleby1(Rest):

    @auth
    def _GET(self, *param, **params):
        host_id = self.chk_hostby1(param)
        if host_id is None: return web.notfound()

        rule_id = param[1]
        if not validates_param_id(self, rule_id):
            return web.notfound(self.view.alert)

        kit = KaresansuiIpTables()
        kit.firewall_xml = kit.read_firewall_xml()

        rules = kit.get_rules()
        cnt = 1
        for rule in rules:
            if cnt == int(rule_id):
                self.view.rule = rule
                break
            cnt = cnt + 1

        if self.is_mode_input():
            self.view.targets = kit.basic_targets['filter']
            self.view.protocols = kit.chain_protos
            self.view.netinfo = get_ifconfig_info()
            devtype_regexs = {
                "phy":"^(lo|eth)",
                "vir":"^(xenbr|virbr|vif|veth)",
                }
            devtype_phy_regex = re.compile(r"%s" % devtype_regexs['phy'])
            devtype_vir_regex = re.compile(r"%s" % devtype_regexs['vir'])

            devs = {}
            devs['phy'] = []
            devs['vir'] = []
            devs['oth'] = []
            cidrs = []
            ips = []
            for dev,dev_info in get_ifconfig_info().iteritems():
                try:
                    if devtype_phy_regex.match(dev):
                        devs['phy'].append(dev)
                    elif devtype_vir_regex.match(dev):
                        devs['vir'].append(dev)
                    else:
                        devs['oth'].append(dev)
                    if dev_info['ipaddr'] is not None:
                        if not dev_info['ipaddr'] in ips:
                            ips.append(dev_info['ipaddr'])
                    if dev_info['cidr'] is not None:
                        if not dev_info['cidr'] in cidrs:
                            cidrs.append(dev_info['cidr'])
                except:
                    pass
            devs['phy'].sort()
            devs['vir'].sort()
            devs['oth'].sort()
            self.view.devs = [{'Physical' : devs['phy']},
                              {'Virtual' : devs['vir']},
                              {'Other' : devs['oth']},
                              ]
            self.view.cidrs = cidrs
            self.view.ips = ips
            return True
        else:
            return web.nomethod()

    @auth
    def _PUT(self, *param, **params):
        host_id = self.chk_hostby1(param)
        if host_id is None: return web.notfound()
        
        if not validates_rule(self):
            return web.badrequest(self.view.alert)

        rule_id = int(param[1])
        if not validates_param_id(self, rule_id):
            return web.notfound(self.view.alert)


        self.view.host_id = host_id

        kit = KaresansuiIpTables()
        kit.firewall_xml = kit.read_firewall_xml()

        rule_info = {"target" : self.input.target,
                     "protocol" : self.input.protocol,
                     "source" : self.input.source,
                     "destination" : self.input.destination,
                     "source-port" : self.input.sport,
                     "destination-port" : self.input.dport,
                     "in-interface" : self.input.inif,
                     "out-interface" : self.input.outif,
                     }
        rule_id = kit.modify_rule(rule_id,rule_info)
        kit.write_firewall_xml()
        
        return web.seeother("%s?mode=input" % web.ctx.path)


    @auth
    def _DELETE(self, *param, **params):
        host_id = self.chk_hostby1(param)
        if host_id is None: return web.notfound()

        rule_id = param[1]
        if not validates_param_id(self, rule_id):
            return web.notfound(self.view.alert)


        new_rules = []

        kit = KaresansuiIpTables()
        kit.firewall_xml = kit.read_firewall_xml()
        kit.delete_rule(int(rule_id))
        kit.write_firewall_xml()
        return web.seeother("%s.part" % web.ctx.path[:web.ctx.path.rfind('/')])

urls = (
    '/host/(\d+)/firewall/rule/(\d+)/?(\.part)$', HostBy1FirewallRuleby1,
    )
