#coding:utf-8
import sys
from sunhpc.core.utils import CommandError
class IPAddr:
    def __init__(self, addr):
        # str: 255.255.0.0 -> 0.0.255.255
        if type(addr) == str:
            self.list = list(map(int, addr.split('.')))
            self.list.reverse()
        else:
            self.list = []
            # addr=255 &后: 255 | addr=256 &后: addr+1,target步进+1
            self.list.append((addr & 0x000000ff))
            # addr=255 &后: target=0 | addr=256 &后: target=1 addr+255, target步进+1
            self.list.append((addr & 0x0000ff00) >> 8)
            # Same as above
            self.list.append((addr & 0x00ff0000) >> 16)
            # Same as above
            self.list.append(((addr & 0xff000000) >> 24) & 0x000000ff)

    def address(self):
        return ((self.list[3] << 24) +
                (self.list[2] << 16) +
                (self.list[1] << 8) + self.list[0])

    def __call__(self):
        return self.address()

    def __getitem__(self, i):
        return self.list[i]

    def __setitem__(self, i, v):
        self.list[i] = v

    def __add__(self, n):
        return IPAddr(self.address() + n)

    def __sub__(self, n):
        return IPAddr(self.address() - n)

    def __invert__(self):
        return ~self.address()

    def __or__(self, o):
        return self.address() | o.address()

    def __and__(self, o):
        return self.address() & o.address()

    def __xor__(self, o):
        return self.address() ^ o.address()

    def __repr__(self):
        # 只使用此类则原路返回地址.
        return '%d.%d.%d.%d' % ( self.list[3], self.list[2],
                                 self.list[1], self.list[0] )

class IPGenerator:

    def __init__(self, network, netmask=None):

        self.network = IPAddr(network)
        # If no netmask was provided infer it from the address
        #
        # 0*   - class A
        # 10*  - class B
        # 110* - class C

        if not netmask:
            if self.network()   & 0x80 == 0x00:
                self.netmask = IPAddr('255.0.0.0')
            elif self.network() & 0xc0 == 0x80:
                self.netmask = IPAddr('255.255.0.0')
            elif self.network() & 0xe0 == 0xc0:
                self.netmask = IPAddr('255.255.255.0')
            else:
                print ('not a unicast address %s' % self.network)
                sys.exit(-1)
        else:
            self.netmask = IPAddr(netmask)

        # Set the initial address to the top of the address range.
        self.addr = IPAddr(self.network | IPAddr(~self.netmask))

    def curr(self):
        if (self.addr & IPAddr(~self.netmask)) == ~self.netmask:
            raise CommandError('At top of address range')

        if (self.addr & IPAddr(~self.netmask)) == 0x00:
            raise CommandError('At bottom of address range')

        return self.addr

    def dec(self):
        return self.next()

    def get_network(self):
        return "%s" % IPAddr(self.addr & self.netmask)

    def next(self, n=-1):
        addr = self.addr + n

        if (addr & IPAddr(~self.netmask)) == ~self.netmask:
            raise CommandError('At top of address range')

        if (addr & IPAddr(~self.netmask)) == 0x00:
            raise CommandError('At bottom of address range')

        self.addr = addr
        return self.addr

if __name__ == '__main__':
    a = IPGenerator('10.1.1.0', '255.255.255.128')
    print (a.curr())
    a.next(-126)
    print (a.curr())
