"""
    revisionhistory_test
"""
from mceditlib.revisionhistory import RevisionHistory
from mceditlib.test.templevel import TempFile

import logging

log = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)


import pytest

from mceditlib import nbt

@pytest.fixture
def history():
    filename = "test_files/AnvilWorld"
    tmpname = TempFile(filename)
    return RevisionHistory(tmpname)

def readChunkTag(rev, cx, cz):
    return nbt.load(buf=rev.readChunkBytes(cx, cz, ""))

def writeChunkTag(rev, cx, cz, tag):
    return rev.writeChunkBytes(cx, cz, "", tag.save(compressed=False))


def testRevision(history):
    revA = history.createRevision()
    log.info("revA")
    # rev A @1 - touch chunk 1
    cx, cz = iter(revA.chunkPositions("")).next()
    chunk = readChunkTag(revA, cx, cz)

    old_tag = tag = nbt.load(buf=history.rootFolder.readChunkBytes(cx, cz, ""))

    assert readChunkTag(history.rootNode, cx, cz) == tag
    assert chunk == tag
    chunk["Level"]["test"] = nbt.TAG_String("test string")

    writeChunkTag(revA, cx, cz, chunk)

    tag = readChunkTag(revA, cx, cz)
    assert "test" in tag["Level"] and tag["Level"]["test"].value == "test string"

    revB = history.createRevision()
    log.info("revB")

    # rev B @2 - delete chunk 2
    tag = readChunkTag(revB, cx, cz)
    assert "test" in tag["Level"] and tag["Level"]["test"].value == "test string"

    revB.deleteChunk(cx+1, cz, "")
    assert not revB.containsChunk(cx+1, cz, "")

    revC = history.createRevision()
    log.info("revC")

    # rev C @3 - delete file
    assert not revC.containsChunk(cx+1, cz, "")
    revC.deleteFile("level.dat")

    assert not revC.containsFile("level.dat")

    changes = revC.getChanges()
    assert changes.chunks[""] == set()
    assert changes.files == {"level.dat"}

    tailRev = history.getRevision(0)

    history.writeAllChanges()

    # initial folder (rev idx 0) and following nodes replaced by reverse nodes
    # rev C @3 replaced by initial folder
    assert revC.invalid

    revC = history.getHead()
    assert tailRev is revC

    changes = revC.getChanges()
    assert changes.chunks[""] == set()
    assert changes.files == {"level.dat"}

    # rev D - create chunk 3
    revD = history.createRevision()
    log.info("revD")

    assert not revD.containsFile("level.dat")
    writeChunkTag(revD, 1000, 1000, old_tag)

    assert not history.rootFolder.containsFile("level.dat")
    assert not history.rootFolder.containsChunk(cx+1, cz, "")

    assert "test" in tag["Level"]
    tag = readChunkTag(history.rootFolder, cx, cz)
    assert tag != old_tag
    assert "test" in tag["Level"]

    # grab rev B
    revBagain = history.getRevision(2)
    assert "test" in readChunkTag(revBagain, cx, cz)["Level"]
    assert not revBagain.containsChunk(cx+1, cz, "")

    # rev B should be read only
    with pytest.raises(IOError):
        writeChunkTag(revBagain, cx, cz, old_tag)

    # check all changes so far
    allChanges = history.getRevisionChanges(0, revD)
    assert allChanges.chunks[""] == {(cx, cz), (cx+1, cz), (1000, 1000)}
    assert allChanges.files == {"level.dat"}

    # insert rev E after rev B
    # world folder is now at the end of an orphan chain at rev @2
    # orphaned revisions are read only and still valid, but do not appear in the history
    revE = history.createRevision(2)
    assert "test" in readChunkTag(revE, cx, cz)["Level"]
    assert not revE.containsChunk(cx+1, cz, "")

    history.close()


