using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using VCRlogic;

namespace VCRlogic
{
    public static class SMtape
    {
        private static StateTape _concreteState;

        public delegate void TapeEventHandler();

        public static event TapeEventHandler evIntape;

        public static event TapeEventHandler evOuttape;

        public static event TapeEventHandler evEndtape;

        public static event TapeEventHandler evNoendtape;


        public static void initSMtape()
        {
            setState(new StapeNoTapeIn());
        }

        public static void setState(StateTape e)
        {
            _concreteState = null;
            _concreteState = e;
        }

        public static StateTape getState()
        {
            return _concreteState;
        }

        public static void insertTape()
        {
            if (evIntape != null)
            {
                evIntape();
            }
        }

        public static void ejectTape()
        {
            if (evOuttape != null)
            {
                evOuttape();
            }
        }


        public static void endTape()
        {
            if (evEndtape != null)
            {
                evEndtape();
            }
        }

        public static void notEndTape()
        {
            if (evNoendtape != null)
            {
                evNoendtape();
            }
        }
    }

    public abstract class StateTape
    {
        public abstract void evIntape();

        public abstract void evOuttape();

        public abstract void evEndtape();

        public abstract void evNotendtape();
    }


    public class StapeNoTapeIn : StateTape
    {
        public StapeNoTapeIn()
        {
            Debug.Print("NoTapeIn\n");

            // sub to event
            SMtape.evIntape += evIntape;
        }

        public override void evIntape()
        {
            //unsub
            SMtape.evIntape -= evIntape;

            SMtape.setState(new StapeTapeInNotEnd());
        }

        public override void evOuttape()
        {
        }

        public override void evEndtape()
        {
        }

        public override void evNotendtape()
        {
        }
    }


    public class StapeTapeInNotEnd : StateTape
    {
        public StapeTapeInNotEnd()
        {
            Debug.Print("TapeInNotEnd\n");

            SMvcr.tapeBeginn();

            //sub
            SMtape.evOuttape += evOuttape;
            SMtape.evEndtape += evEndtape;
        }

        public override void evIntape()
        {
        }

        public override void evOuttape()
        {
            //unsub
            SMtape.evOuttape -= evOuttape;
            SMtape.evEndtape -= evEndtape;
            SMtape.setState(new StapeNoTapeIn());
        }

        public override void evEndtape()
        {
            //unsub
            SMtape.evOuttape -= evOuttape;
            SMtape.evEndtape -= evEndtape;
            SMtape.setState(new StapeTapeInEnd());
        }

        public override void evNotendtape()
        {
        }
    }


    public class StapeTapeInEnd : StateTape
    {
        public StapeTapeInEnd()
        {
            Debug.Print("TapeInEnd\n");

            SMvcr.tapeEnd();

            SMtape.evOuttape += evOuttape;
            SMtape.evNoendtape += evNotendtape;
        }

        public override void evIntape()
        {
        }

        public override void evOuttape()
        {
            SMtape.evOuttape -= evOuttape;
            SMtape.evNoendtape -= evNotendtape;
            SMtape.setState(new StapeNoTapeIn());
        }

        public override void evEndtape()
        {
        }

        public override void evNotendtape()
        {
            SMtape.evOuttape -= evOuttape;
            SMtape.evNoendtape -= evNotendtape;
            SMtape.setState(new StapeTapeInNotEnd());
        }
    }
}