#!/usr/bin/python3
# Jednosměrné spojové seznamy s předáváním na začátek

import sys
from typing import Optional


class MyNode:
    def __init__(self, x):
        # Každy prvek si pamatuje hodnotu a následníka
        self.value: int = x
        self.next: Optional[MyNode] = None

    def __str__(self):
        return f"Node({self.value})"


class MyList:
    def __init__(self):
        # Seznam si pamatuje odkaz na svůj první prvek
        self.first: Optional[MyNode] = None

    def prepend(self, x):
        """Zapojí prvek se zadanou hodnotu na začátek seznamu."""
        n = MyNode(x)
        n.next = self.first
        self.first = n

    def print(self):
        n = self.first
        while n:
            print(f"->{n.value}", end="")
            n = n.next
        print()

    def find(self, value):
        node = self.first
        while node is not None and node.value != value:
            node = node.next
        return node

    def _remove_node(self, node: Optional[MyNode], target_node: MyNode):
        if node is None:
            return None
        elif node is target_node:
            return node.next
        else:
            node.next = self._remove_node(node.next, target_node)
            return node

    def remove_node(self, node):
        self.first = self._remove_node(self.first, node)

    def remove_value(self, value):
        tmp = self.find(value)
        while tmp is not None:
            self.remove_node(tmp)
            tmp = self.find(value)

    def pred_node(self, node):
        tmp = self.first
        if self.first is node:
            return None
        else:
            while tmp.next is not None:
                if tmp.next is node:
                    return tmp
                else:
                    tmp = tmp.next
            return None

    def succ_node(self, node):
        tmp = self.first
        while tmp is not None:
            if tmp is node:
                return tmp.next
            else:
                tmp = tmp.next

    def reverse(self):
        if self.first is None:
            return
        pred_node = None
        node = self.first
        while node is not None:
            tmp = node.next
            node.next = pred_node
            pred_node = node
            node = tmp
        self.first = pred_node


if __name__ == "__main__":
    l = MyList()
    for a in [4, 2, 6, 1, 3, 5, 7]:
        l.prepend(a)
    l.print()
    print("Successor and predecessor")
    for a in [4, 2, 6, 1, 3, 5, 7]:
        succ = l.succ_node(l.find(a))
        pred = l.pred_node(l.find(a))
        print(f"{pred}->{a}->{succ}")
    print("Reversed")
    l.reverse()
    l.print()
    for a in [2, 6, 1, 4, 1, 7]:
        print(f"Removing {a}")
        l.remove_value(a)
        l.print()
