public async Task <object> DownloadLastCapturedFile(dynamic input)
        {
            LogMessage($"Downloading last captured file");

            bool deleteFile = HasInputValue(input, "deleteFile")
                ? (bool)input.deleteFile
                : true;

            if (LastCapturedFileInfo == null)
            {
                var result = new NodeResult();
                result.message = "No file has been captured yet";
                result.success = false;

                return(result);
            }

            try
            {
                EnsureCameraSessionOpened();

                string downloadedFilePath = await DownloadFile(LastCapturedFileInfo);

                LogMessage("Last captured file downloaded");

                if (deleteFile)
                {
                    await DeleteLastCapturedFile();
                }

                var result = new MediaResult();
                result.message = "Downloaded file";
                result.path    = downloadedFilePath;
                result.success = true;

                return(result);
            }
            catch (Exception ex)
            {
                return(HandleException(ex));
            }
        }
        public async Task <object> TakePhoto(dynamic input)
        {
            LogMessage("Taking photo");

            var  maxTries = 5;
            var  tries    = 0;
            bool shouldRestartLiveView = false;

            try
            {
                EnsureCameraSessionOpened();

                MainCamera.SaveTo = SaveTo.Host;

                if (MainCamera.IsLiveViewOn)
                {
                    shouldRestartLiveView = HasInputValue(input, "shouldRestartLiveView")
                        ? (bool)input.shouldRestartLiveView
                        : true;
                    MainCamera.StopLiveView();
                }

                await MainCamera.SetCapacity(4096, 999999999);

                while (true)
                {
                    CaptureSuccess = false;

                    DownloadReadyWaiter.Reset();
                    await MainCamera.TakePhoto();

                    // TODO: make it timeout
                    // https://stackoverflow.com/questions/22678428/any-way-to-trigger-timeout-on-waitone-immediately
                    DownloadReadyWaiter.WaitOne();

                    if (CaptureSuccess)
                    {
                        break;
                    }
                    else if (tries >= maxTries)
                    {
                        throw new Exception($"Photo not taken in {tries} tries");
                    }
                    else
                    {
                        LogMessage("Retrying to take photo");
                        await Task.Delay(100);

                        tries++;
                    }
                }

                string downloadedFilePath = await DownloadFile(LastCapturedFileInfo);

                var result = new MediaResult();
                result.message = "Photo taken";
                result.path    = downloadedFilePath;
                result.success = true;

                return(result);
            }
            catch (Exception ex) {
                return(HandleException(ex));
            }
            finally
            {
                if (shouldRestartLiveView && IsCameraSessionOpened())
                {
                    MainCamera.StartLiveView();
                }
            }
        }