import re
import buffer, default, dirutil, regex, util, window
from point import Point
from method import Method, Argument

num_re = re.compile(r'(?:-?[1-9][0-9]*|0x[0-9A-Fa-f]+|0[0-7]+|0)')

def find_next_number(w, offset=0):
    b = w.buffer
    x, y = w.logical_cursor().xy()
    x += offset
    while y < len(b.lines):
        m = num_re.search(b.lines[y], x)
        if m:
            return (Point(m.start(), y), Point(m.end(), y))
        x = 0
        y += 1
    return (None, None)
def find_prev_number(w, offset=0):
    b = w.buffer
    x, y = w.logical_cursor().xy()
    x += offset
    while y >= 0:
        m = m2 = num_re.search(b.lines[y], 0, x)
        while m2:
            m = m2
            m2 = num_re.search(b.lines[y], m2.end(), x)
        if m:
            return (Point(m.start(), y), Point(m.end(), y))
        y -= 1
        x = len(b.lines[y])
    return (None, None)

def get_converter(s):
    if s.startswith('0x'):
        return hex
    elif s.startswith('0') and len(s) > 1:
        return oct
    else:
        return str

class GotoPrevNumber(Method):
    '''Move the cursor to the start of the word to the right'''
    def _execute(self, w, **vargs):
        (p1, p2) = find_prev_number(w, -1)
        if p1 is not None:
            w.goto(p1)

class GotoNextNumber(Method):
    def _execute(self, w, **vargs):
        (p1, p2) = find_next_number(w, 1)
        if p1 is not None:
            w.goto(p2.add(-1, 0))

class Increment(Method):
    '''Increment the next number'''
    def _execute(self, w, **vargs):
        (p1, p2) = find_next_number(w)
        if p1 is None:
            return
        s    = w.buffer.lines[p1.y][p1.x:p2.x]
        num  = int(s)
        conv = get_converter(s)
        w.set_error('found %r' % num)
        w.delete(p1, p2)
        s2 = conv(num + 1)
        w.insert_string(p1, s2)
        w.goto(p1)

class Decrement(Method):
    '''Decrement the next number'''
    def _execute(self, w, **vargs):
        (p1, p2) = find_next_number(w)
        if p1 is None:
            return
        s    = w.buffer.lines[p1.y][p1.x:p2.x]
        num  = int(s)
        conv = get_converter(s)
        w.set_error('found %r' % num)
        w.delete(p1, p2)
        s2 = conv(num - 1)
        w.insert_string(p1, s2)
        w.goto(p1)