from collections.abc import MutableSequence

from .storage import get_storage


class plist(MutableSequence):
    def __init__(self, name, initial=None):
        self._storage = get_storage()
        named_id = self._storage.get_named(name, "list")
        if named_id is None:
            self.id = self._storage.generate_id()
            self._data = list(initial) if initial is not None else []
            self._persist()
            self._storage.set_named(name, self.id, "list")
        else:
            self.id = named_id
            loaded = self._storage.get(named_id)
            if loaded is None:
                self._data = list(initial) if initial is not None else []
                self._persist()
            else:
                object_type, data = loaded
                if object_type != "list":
                    raise TypeError("Stored object is not a list.")
                self._data = list(data)

    @classmethod
    def load(cls, name, initial=None):
        return cls(name=name, initial=initial)

    def __len__(self):
        return len(self._data)

    def __getitem__(self, index):
        return self._data[index]

    def __setitem__(self, index, value):
        self._data[index] = value
        self._persist()

    def __delitem__(self, index):
        del self._data[index]
        self._persist()

    def insert(self, index, value):
        self._data.insert(index, value)
        self._persist()

    def __iter__(self):
        return iter(self._data)

    def __repr__(self):
        return repr(self._data)

    def __eq__(self, other):
        if isinstance(other, plist):
            return self._data == other._data
        return self._data == other

    def append(self, value):
        self._data.append(value)
        self._persist()

    def extend(self, values):
        self._data.extend(values)
        self._persist()

    def pop(self, index=-1):
        value = self._data.pop(index)
        self._persist()
        return value

    def clear(self):
        self._data.clear()
        self._persist()

    def remove(self, value):
        self._data.remove(value)
        self._persist()

    def reverse(self):
        self._data.reverse()
        self._persist()

    def sort(self, *args, **kwargs):
        self._data.sort(*args, **kwargs)
        self._persist()

    def __iadd__(self, other):
        self._data += list(other)
        self._persist()
        return self

    def __imul__(self, other):
        self._data *= other
        self._persist()
        return self

    def _persist(self):
        self._storage.save(self.id, "list", self._data)
