/// <summary>
    /// Controls knife movement
    /// </summary>
    /// <param name="x">X positino of the knife</param>
    private void CheckKnife_(float x)
    {
        const float KNIFE_MOVEMENT = 0.3f;

        // if right, and meant to be going right
        if (x > 0.9f && _knifeTarget > 0)
        {
            Chef.Knife.Translate(new Vector3(KNIFE_MOVEMENT / 5, 0, 0));
            _knifeTarget = -1;
        }
        // if left, and meant to be going left
        else if (x < -0.9f && _knifeTarget < 0)
        {
            Chef.BreadChopSound.Play();

            Chef.Knife.Translate(new Vector3(-KNIFE_MOVEMENT, 0, 0));
            _knifeTarget = 1;

            // once reached the end
            if (Chef.Knife.localPosition.x <= -3f)
            {
                // hide bread, knife
                ShowBreadOptions_(false);
                Chef.Knife.gameObject.SetActive(false);
                _action = ChefAction.FacingBoard;

                //move to next stage
                Chef.SelectionHand.gameObject.SetActive(true);
                Chef.ChopBunRendererBottom.gameObject.SetActive(false);
                Chef.TopBun.gameObject.SetActive(true);
                SpawnBread_(false);
                UpdateHelp_();
            }
        }
    }
 /// <summary>
 /// Handles the selection and squirting of sauce
 /// </summary>
 /// <param name="index">The index of the selected sauce</param>
 private void DoSauce_(int index)
 {
     // move selected bottle up (change state)
     Chef.SelectionHand.gameObject.SetActive(false);
     _action = ChefAction.SauceIntoPosition;
     StartCoroutine(MoveSauceUp_(index));
 }
    /// <summary>
    /// Moves the plate off the screen and serves the burger
    /// </summary>
    IEnumerator ServeToCustomer_()
    {
        _action = ChefAction.Serving;

        var rightPosition = Chef.PlatePosition() + 12f;

        // move plate right
        while (Chef.Plate.localPosition.x < rightPosition)
        {
            Chef.Plate.Translate(new Vector3(0.25f, 0, 0));
            yield return(new WaitForSeconds(0.01f));
        }

        // give the burger to the customer
        _customerHandler.CustomerServed(_burgerSelections);

        // update UI with next 10 orders
        Chef.DisplayOrders(_customerHandler.GetNextOrders(10));

        // remove unused items
        ClearPlate_();

        yield return(new WaitForSeconds(0.25f));

        // move plate left
        while (Chef.Plate.localPosition.x > Chef.PlatePosition())
        {
            Chef.Plate.Translate(new Vector3(-0.25f, 0, 0));
            yield return(new WaitForSeconds(0.01f));
        }
        Chef.Plate.localPosition = new Vector3(Chef.PlatePosition(), Chef.Plate.localPosition.y, Chef.Plate.localPosition.z);

        // next action
        _action = ChefAction.FacingBoard;
    }
    /// <summary>
    /// Moves the selected bottle up, and the squirt bottle down
    /// </summary>
    /// <param name="index">The bottle to move</param>
    private IEnumerator MoveSauceUp_(int index)
    {
        _selectedSauce = (SauceType)index;

        var bottle = Chef.SauceBottles[index];

        // move bottle up
        while (bottle.localPosition.y < 8)
        {
            bottle.Translate(new Vector3(0, 14 * Time.deltaTime, 0));
            yield return(new WaitForSeconds(0.01f));
        }

        // change sauce appearance
        Chef.SquirtBottle.BottleImage.sprite = LicenseToGrillController.Instance.SauceImages[index];
        Chef.SquirtBottle.SauceImage.color   = ColourFetcher.GetSauceColour(index);

        // change particle colour
        var particleMain = Chef.SquirtBottle.SquirtParticle.main;

        particleMain.startColor = ColourFetcher.GetSauceColour(index);

        // move big bottle down
        while (Chef.SquirtBottle.transform.localPosition.y > SAUCE_SQUIRT_BOTTLE_Y_POSITION)
        {
            Chef.SquirtBottle.transform.Translate(new Vector3(0, -14 * Time.deltaTime, 0));
            yield return(new WaitForSeconds(0.01f));
        }

        _action = ChefAction.SquirtingSauce;
        Chef.SaucePlatform.gameObject.SetActive(true);
        Chef.Help_Sauce.SetActive(true);
    }
    /// <summary>
    /// Spawn bread
    /// </summary>
    void SpawnBread_(bool top)
    {
        Sprite  sprite  = null;
        BunType bunType = BunType.Brioche;

        switch (_selectedBread)
        {
        // spawn brioche
        case SelectionType.BriocheBun:
            sprite  = top ? LicenseToGrillController.Instance.BreadTop[0] : LicenseToGrillController.Instance.BreadBottoms[0];
            bunType = BunType.Brioche;
            break;

        // spawn sesame
        case SelectionType.SesameBun:
            sprite  = top ? LicenseToGrillController.Instance.BreadTop[1] : LicenseToGrillController.Instance.BreadBottoms[1];
            bunType = BunType.Sesame;
            break;

        // spawn brown
        case SelectionType.BrownBun:
            sprite  = top ? LicenseToGrillController.Instance.BreadTop[2] : LicenseToGrillController.Instance.BreadBottoms[2];
            bunType = BunType.Brown;
            break;
        }

        // spawn an item
        if (sprite != null)
        {
            SpawnSomething_(LicenseToGrillController.Instance.FoodPlateItemPrefab, sprite, new BurgerBun(bunType), false);
            ShowBreadOptions_(false);
            _action = ChefAction.FacingBoard;
        }
    }
    /// <summary>
    /// Begins chopping an item
    /// </summary>
    private void StartVegChop_(BurgerVegType veg)
    {
        bool doChop = false;

        ChopItem choppingItem = null;

        switch (veg)
        {
        case BurgerVegType.Lettuce:
            SpawnVeg_(BurgerVegType.Lettuce);
            break;

        case BurgerVegType.Tomato:
            doChop       = true;
            choppingItem = Chef.ChoppingTomato;
            _action      = ChefAction.ChoppingTomato;
            break;

        case BurgerVegType.Pickle:
            doChop       = true;
            choppingItem = Chef.ChoppingPickle;
            _action      = ChefAction.ChoppingPickle;
            break;
        }

        if (doChop)
        {
            Chef.SelectionHand.gameObject.SetActive(false);
            choppingItem.Initialise(veg, VegChopComplete_);
            choppingItem.gameObject.SetActive(true);
        }
    }
    /// <summary>
    /// Show the behaviour for chopping bread
    /// </summary>
    private void ChopBread_()
    {
        // onnly do it if the hand is in a valid location
        if (_currentItem.Count > 0)
        {
            _selectedBread = _currentItem[0].ObjectType;

            // show the knife and hide the bread
            Chef.Knife.gameObject.SetActive(true);
            Chef.Knife.localPosition = new Vector3(3f, -1.25f, -0.14f);
            ShowBreadOptions_(false);

            // show big bread
            Chef.ChopBunRendererBottom.gameObject.SetActive(true);

            // set bread image
            SetBunChopImage_();

            // start chopping
            Chef.SelectionHand.gameObject.SetActive(false);
            _action      = ChefAction.ChoppingBread;
            _knifeTarget = -1;
            UpdateHelp_();
        }
    }
 /// <summary>
 /// Cancels the veg chopping process
 /// </summary>
 /// <param name="veg">The chopping to cancel</param>
 private void CancelVegChop_(ChopItem veg)
 {
     if (veg.CanCancel())
     {
         veg.ResetItem();
         _action = ChefAction.FacingBoard;
         Chef.SelectionHand.gameObject.SetActive(true);
     }
 }
    /// <summary>
    /// Display the confirmation popup
    /// </summary>
    /// <param name="confirmCallback">The callback to call upon completion</param>
    /// <param name="message">The message to display</param>
    void Confirm_(Action confirmCallback, string message)
    {
        // set actions
        _actionCopy      = _action;
        _confirmCallback = confirmCallback;
        _action          = ChefAction.Confirmation;

        // show popup
        Chef.ConfirmPopup.SetActive(true);
        Chef.ConfirmPopupText.text = message;
    }
    /// <summary>
    /// Function that can be called from other scripts once an action is complete
    /// </summary>
    /// <param name="newAction"></param>
    void UpdateAction_(ChefAction newAction)
    {
        _action = newAction;

        // does anything need done with this new state?
        switch (_action)
        {
        case ChefAction.SauceReturn:
            // move bottles back to position
            StartCoroutine(MoveSauceDown_());
            break;
        }
    }
    /// <summary>
    /// Throws a patty away
    /// </summary>
    private IEnumerator DisposePatty_()
    {
        // only do this if the burger is active
        if (Chef.Burgers[_selectedPattyIndex].gameObject.activeInHierarchy)
        {
            _disposing = true;
            var targetPosition = Chef.BinY;

            // continue until reached the top
            while (Chef.BinPatty.localPosition.y < targetPosition)
            {
                yield return(new WaitForSeconds(0.001f));

                Chef.BinPatty.Translate(new Vector3(0, 0.2f, 0));
            }

            Chef.Burgers[_selectedPattyIndex].CookedBar.SetActive(false);

            // disable collider
            Chef.Burgers[_selectedPattyIndex].GetComponent <BoxCollider2D>().enabled = false;

            // lose points
            _wastePoints          -= WASTE_POINTS_BURGER;
            Chef.BinPattyText.text = "-" + WASTE_POINTS_BURGER;

            // fade away the message
            for (float i = 1f; i >= 0; i -= 0.1f)
            {
                Chef.BinPattyText.color = new Color(1, 1, 1, i);
                yield return(new WaitForSeconds(0.1f));
            }
            Chef.BinPattyText.color = new Color(1, 1, 1, 0);

            // reset action
            _action = ChefAction.FacingGrill;

            // move bin down
            targetPosition = Chef.BinY - 8f;
            while (Chef.BinPatty.localPosition.y > targetPosition)
            {
                yield return(new WaitForSeconds(0.001f));

                Chef.BinPatty.Translate(new Vector3(0, -0.2f, 0));
            }

            // reset the burger
            Chef.Burgers[_selectedPattyIndex].ResetBurger();
            _disposing = false;
        }
    }
    /// <summary>
    /// Slides the burger choices on to the screen
    /// </summary>
    private IEnumerator SlideBurgersUp_()
    {
        var targetPosition = Chef.BurgerTrayY;

        // continue until reached the top
        while (Chef.BurgerTray.localPosition.y < targetPosition)
        {
            yield return(new WaitForSeconds(0.001f));

            Chef.BurgerTray.Translate(new Vector3(0, 0.2f, 0));
        }

        // next action
        _action = ChefAction.SelectingBurger;
    }
    public override void OnR1()
    {
        if (!PauseGameHandler.Instance.IsPaused())
        {
            // move the camera based on the current action
            switch (_action)
            {
            case ChefAction.FacingGrill:
                Chef.CameraRight_();
                _action = ChefAction.FacingBoard;
                UpdateHelp_();
                break;
            }
        }

        base.OnR1();
    }
    /// <summary>
    /// Slides the burger choices off the screen
    /// </summary>
    private IEnumerator SlideBurgersDown_()
    {
        _action = ChefAction.SlidingBurgerBoard;

        // move sufficiently off the screen
        var targetPosition = Chef.BurgerTrayY - 8;

        // continue until reached the top
        while (Chef.BurgerTray.localPosition.y > targetPosition)
        {
            yield return(new WaitForSeconds(0.001f));

            Chef.BurgerTray.Translate(new Vector3(0, -0.2f, 0));
        }

        // next action
        _action = ChefAction.FacingGrill;
    }
    /// <summary>
    /// Override function for the circle button
    /// </summary>
    public override void OnCircle()
    {
        base.OnCircle();
        if (PauseGameHandler.Instance.IsPaused())
        {
            return;
        }
        switch (_action)
        {
        case ChefAction.SelectingBurger:
            StartCoroutine(SlideBurgersDown_());
            _action = ChefAction.FacingGrill;
            break;

        case ChefAction.SelectingBread:
            ShowBreadOptions_(false);
            _action = ChefAction.FacingBoard;
            SelectFirstItem_();
            break;

        case ChefAction.SquirtingSauce:
            if (!_squirting)
            {
                _action = ChefAction.SauceReturn;
                StartCoroutine(MoveSauceDown_(true));
            }
            break;

        case ChefAction.ChoppingTomato:
            CancelVegChop_(Chef.ChoppingTomato);
            break;

        case ChefAction.ChoppingPickle:
            CancelVegChop_(Chef.ChoppingPickle);
            break;

        case ChefAction.Confirmation:
            _action = _actionCopy;
            Chef.ConfirmPopup.SetActive(false);
            break;
        }
    }
    /// <summary>
    /// Override function for the touchpad button
    /// </summary>
    public override void OnTouchpad()
    {
        // move the camera based on the current action
        switch (_action)
        {
        case ChefAction.FacingGrill:
        case ChefAction.FacingBoard:
        case ChefAction.SelectingBread:
        case ChefAction.SelectingBurger:
        case ChefAction.ChoppingBread:
        case ChefAction.ClearingPlate:
            _actionCopy = _action;
            _action     = ChefAction.ViewingOrders;
            Chef.OrderList.gameObject.SetActive(true);
            break;

        case ChefAction.ViewingOrders:
            _action = _actionCopy;
            Chef.OrderList.gameObject.SetActive(false);
            break;
        }
    }
    /// <summary>
    /// Moves the selected bottle down, and the squirt bottle up
    /// </summary>
    /// <param name="index">The bottle to move</param>
    private IEnumerator MoveSauceDown_(bool cancelled = false)
    {
        Chef.Help_Sauce.SetActive(false);

        if (!cancelled)
        {
            yield return(new WaitForSeconds(1f));

            _burgerSelections.Add(new BurgerSauce(_selectedSauce, Chef.SquirtBottle.SauceImage.transform.localScale.x));
            _burgerElements.Add(null);
            _burgerItemIndex++;
        }

        // the highest bottle is the one to use
        var bottle = Chef.SauceBottles.Where(b => b.localPosition.y >= Chef.SauceBottles.Max(c => c.localPosition.y)).First();

        // move big bottle up
        while (Chef.SquirtBottle.transform.localPosition.y < 11)
        {
            Chef.SquirtBottle.transform.Translate(new Vector3(0, 14 * Time.deltaTime, 0));
            yield return(new WaitForSeconds(0.01f));
        }

        // move bottle down
        while (bottle.localPosition.y > _saucesYPosition)
        {
            bottle.Translate(new Vector3(0, -14 * Time.deltaTime, 0));
            yield return(new WaitForSeconds(0.01f));
        }
        bottle.transform.localPosition = new Vector3(bottle.localPosition.x, _saucesYPosition, bottle.localPosition.z);

        // continue to next action
        _action = ChefAction.FacingBoard;
        Chef.SelectionHand.gameObject.SetActive(true);
        Chef.SaucePlatform.gameObject.SetActive(false);
    }
 /// <summary>
 /// Stops the player
 /// </summary>
 public void Finished()
 {
     _action = ChefAction.NotStarted;
 }
    /// <summary>
    /// Clears all items from the plate
    /// </summary>
    IEnumerator TipPlate_()
    {
        _action = ChefAction.ClearingPlate;

        var targetPosition = Chef.BinY;

        // slide bin in
        while (Chef.Bin.localPosition.y < targetPosition)
        {
            yield return(new WaitForSeconds(0.001f));

            Chef.Bin.Translate(new Vector3(0, 0.2f, 0));
        }

        // make all elements fall
        foreach (var item in _burgerElements)
        {
            item.GetComponent <BoxCollider2D>().enabled = false;
        }

        // get waste points for all items wasted
        var wastePointsPrevious = _wastePoints;

        foreach (var item in _burgerSelections)
        {
            if (item is BurgerPatty)
            {
                _wastePoints -= WASTE_POINTS_BURGER;
            }
            if (item is BurgerVeg)
            {
                _wastePoints -= WASTE_POINTS_VEG;
            }
            if (item is BurgerBun)
            {
                _wastePoints -= WASTE_POINTS_BUN;
            }
            if (item is BurgerSauce)
            {
                _wastePoints -= WASTE_POINTS_SAUCE;
            }
        }

        // display wasted points
        var difference = wastePointsPrevious - _wastePoints;

        Chef.BinText.text = "-" + difference;

        // fade out wasted points text
        for (float i = 1f; i >= 0; i -= 0.1f)
        {
            Chef.BinText.color = new Color(1, 1, 1, i);
            yield return(new WaitForSeconds(0.1f));
        }
        Chef.BinText.color = new Color(1, 1, 1, 0);

        yield return(new WaitForSeconds(1f));

        // remove elements from plate
        ClearPlate_();

        targetPosition = Chef.BinY - 8f;

        // slide bin out
        while (Chef.Bin.localPosition.y > targetPosition)
        {
            yield return(new WaitForSeconds(0.001f));

            Chef.Bin.Translate(new Vector3(0, -0.2f, 0));
        }

        _action = ChefAction.FacingBoard;
    }
 /// <summary>
 /// Callback when chopping veg is complete
 /// </summary>
 void VegChopComplete_(BurgerVegType veg)
 {
     SpawnVeg_(veg);
     Chef.SelectionHand.gameObject.SetActive(true);
     _action = ChefAction.FacingBoard;
 }
    /// <summary>
    /// When the spacebar is pressed
    /// </summary>
    private void CrossPressed_()
    {
        // perform the required action
        switch (_action)
        {
        case ChefAction.FacingGrill:
            if (_selectedPattyIndex > -1)
            {
                if (Chef.Burgers[_selectedPattyIndex].isActiveAndEnabled)
                {
                    // flip
                    if (!(Chef.Burgers.Any(b => b.Flipping())))
                    {
                        _flippedPattyIndex = _selectedPattyIndex;
                        if (_newSideRoutine != null)
                        {
                            StopCoroutine(_newSideRoutine);
                        }
                        StartCoroutine(DoFlip_(() => { _newSideRoutine = StartCoroutine(Chef.Burgers[_flippedPattyIndex].StartNewSide()); }));
                    }
                }
                else
                {
                    // select burger
                    _action = ChefAction.SlidingBurgerBoard;
                    StartCoroutine(SlideBurgersUp_());
                }
            }
            break;

        case ChefAction.FacingBoard:
        {
            if (_currentItem.Count > 0)
            {
                switch (_currentItem[0].ObjectType)
                {
                case SelectionType.Lettuce:
                    StartVegChop_(BurgerVegType.Lettuce);
                    break;

                case SelectionType.Tomato:
                    StartVegChop_(BurgerVegType.Tomato);
                    break;

                case SelectionType.Pickle:
                    StartVegChop_(BurgerVegType.Pickle);
                    break;

                case SelectionType.Sauce:
                    DoSauce_(_currentItem[0].Index);
                    break;

                case SelectionType.BriocheBunTop:
                case SelectionType.SesameBunTop:
                case SelectionType.BrownBunTop:
                    SpawnBread_(true);
                    Chef.TopBun.gameObject.SetActive(false);
                    break;

                case SelectionType.BreadBin:
                    if (_burgerItemIndex == 0)
                    {
                        _action = ChefAction.SelectingBread;
                        ShowBreadOptions_(true);
                    }
                    else
                    {
                        ShowErrorMessage_("Bread option has already been selected");
                    }
                    break;

                case SelectionType.Plate:
                    Confirm_(Serve_, "Are you sure you wish to serve this burger?");
                    break;
                }
            }
            break;
        }

        case ChefAction.SelectingBread:
        {
            if (_currentItem.Count > 0)
            {
                switch (_currentItem[0].ObjectType)
                {
                case SelectionType.BriocheBun:
                case SelectionType.SesameBun:
                case SelectionType.BrownBun:
                    ChopBread_();
                    break;
                }
            }
            break;
        }

        case ChefAction.Confirmation:
        {
            _confirmCallback?.Invoke();
            Chef.ConfirmPopup.SetActive(false);
            break;
        }

        case ChefAction.SelectingBurger:
        {
            DropBurger(1);
            break;
        }
        }
    }
 /// <summary>
 /// Starts the player
 /// </summary>
 public void Activate()
 {
     _action = ChefAction.FacingBoard;
 }