package boq.cctags.cc;

import static boq.utils.misc.Utils.*;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.Vec3;
import net.minecraftforge.common.ForgeDirection;
import boq.cctags.tag.TagData;
import boq.cctags.tag.TagSize;
import boq.cctags.tag.access.*;
import boq.cctags.tag.access.EntityAccess.IPositionProvider;
import boq.cctags.tag.access.ItemAccess.IStackProvider;
import dan200.computer.api.*;
import dan200.turtle.api.ITurtleAccess;

public abstract class TurtlePeripheral implements IHostedPeripheral {

    protected final ITurtleAccess turtle;

    protected ITagAccess tagAccess = AccessUtils.NULL;

    public TurtlePeripheral(ITurtleAccess turtle) {
        this.turtle = turtle;
    }

    protected ForgeDirection getDirection(String direction) {
        int turtleDir = turtle.getFacingDir();
        ForgeDirection front = ForgeDirection.VALID_DIRECTIONS[turtleDir];
        return SidesHelper.localToWorld(front, direction);
    }

    protected final static String[] commonMethods = { "isTagValid", "scanForTag", "selectFromSlot", "contents", "write", "size", "serial", "library", "source" };

    @Override
    public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception {
        switch (method) {
            case 0: // isTagValid
                return wrap(tagAccess.isValid());
            case 1: { // scanForTag
                String directionName = checkArg(arguments, 0) ? arguments[0].toString() : null;
                ForgeDirection dir = getDirection(directionName);
                ITagAccess access = AccessUtils.selectTag(turtle.getWorld(), dir, new IPositionProvider() {
                    @Override
                    public Vec3 getPosition() {
                        return turtle.getPosition();
                    }
                });

                if (!access.isValid())
                    return FALSE;

                tagAccess = access;
                return TRUE;
            }
            case 2: {// selectFromSlot
                final int slotId = checkArg(arguments, 0) ? toInt(arguments[0]) : turtle.getSelectedSlot();

                ITagAccess access = new ItemAccess(new IStackProvider() {
                    @Override
                    public ItemStack getStack() {
                        return turtle.getSlotContents(slotId);
                    }
                }, AccessUtils.mergedAccess);

                if (access.isValid()) {
                    tagAccess = access;
                    return TRUE;
                }

                return wrap(false, "Invalid or missing tag");

            }
            case 3: {// contents
                if (!tagAccess.isValid())
                    return wrap("false", "No selected tag");

                String contents = tagAccess.readData().contents;
                return wrap(contents, contents == null ? 0 : contents.length());
            }
            case 4: {// write
                if (!tagAccess.isValid())
                    return wrap("false", "No selected tag");

                String newContents = arguments[0].toString();

                TagData data = tagAccess.readData();
                if (!data.tagSize.check(newContents))
                    return wrap("false", "Message too big");

                data.contents = newContents;
                tagAccess.writeData(data, false);
                return wrap(true, newContents.length());
            }
            case 5: { // size
                if (!tagAccess.isValid())
                    return wrap("false", "No selected tag");

                TagSize size = tagAccess.readData().tagSize;
                return wrap(size.size, size.name);
            }

            case 6: { // serial
                if (!tagAccess.isValid())
                    return wrap("false", "No selected tag");

                int serial = tagAccess.uid();
                return wrap(serial);
            }

            case 7: // library
                return TagLibrary.instance.getLuaLibrary(arguments);

            case 8: // source
                return wrap(tagAccess.name());
        }

        throw new IllegalArgumentException("Invalid method id: " + method);
    }

    @Override
    public boolean canAttachToSide(int side) {
        return false;
    }

    @Override
    public void attach(IComputerAccess computer) {
        MountHelper.mount(computer, "rom/apis/tags", "tags-turtle");

        MountHelper.mount(computer, "rom/programs/follow", "follow");

        MountHelper.mount(computer, "rom/help/follow", "follow-help");
        MountHelper.mount(computer, "rom/help/tag-writer", "turtle-writer-help");
    }

    @Override
    public void detach(IComputerAccess computer) {}

    @Override
    public void update() {}

    @Override
    public void readFromNBT(NBTTagCompound tag) {}

    @Override
    public void writeToNBT(NBTTagCompound tag) {}
}

@@ -1627,34 +1627,33 @@
                 
-IT
+t
 agAccess access 
@@ -1645,23 +1645,16 @@
 gAccess 
-access 
 = Access
@@ -1913,129 +1913,40 @@
     
-if (!access.isValid())%0A                    return FALSE;%0A%0A                tagAccess = access;%0A                return TRUE
+return wrap(tagAccess.isValid())
 ;%0A  
@@ -2121,18 +2121,17 @@
         
-IT
+t
 agAccess
@@ -2135,15 +2135,8 @@
 ess 
-access 
 = ne
@@ -2403,186 +2403,41 @@
     
-if (access.isValid()) %7B%0A                    tagAccess = access;%0A                    return TRUE;%0A                %7D%0A%0A                return wrap(false, %22Invalid or missing tag%22);%0A
+return wrap(tagAccess.isValid());
 %0A   

Reset tag acces after failed scan