/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */

/* global CaptureAudioOptions, CaptureImageOptions, CaptureVideoOptions, CaptureError */
/* global Media, MediaFile, MediaFileData, resolveLocalFileSystemURL, cordova */

exports.defineAutoTests = function () {
    describe('Capture (navigator.device.capture)', function () {
        it('capture.spec.1 should exist', function () {
            expect(navigator.device).toBeDefined();
            expect(navigator.device.capture).toBeDefined();
        });

        it('capture.spec.2 should have the correct properties ', function () {
            expect(navigator.device.capture.supportedAudioModes).toBeDefined();
            expect(navigator.device.capture.supportedImageModes).toBeDefined();
            expect(navigator.device.capture.supportedVideoModes).toBeDefined();
        });

        it('capture.spec.3 should contain a captureAudio function', function () {
            expect(navigator.device.capture.captureAudio).toBeDefined();
            expect(typeof navigator.device.capture.captureAudio === 'function').toBe(true);
        });

        it('capture.spec.4 should contain a captureImage function', function () {
            expect(navigator.device.capture.captureImage).toBeDefined();
            expect(typeof navigator.device.capture.captureImage === 'function').toBe(true);
        });

        it('capture.spec.5 should contain a captureVideo function', function () {
            expect(navigator.device.capture.captureVideo).toBeDefined();
            expect(typeof navigator.device.capture.captureVideo === 'function').toBe(true);
        });

        describe('CaptureAudioOptions', function () {
            it('capture.spec.6 CaptureAudioOptions constructor should exist', function () {
                var options = new CaptureAudioOptions();
                expect(options).toBeDefined();
                expect(options.limit).toBeDefined();
                expect(options.duration).toBeDefined();
            });
        });

        describe('CaptureImageOptions', function () {
            it('capture.spec.7 CaptureImageOptions constructor should exist', function () {
                var options = new CaptureImageOptions();
                expect(options).toBeDefined();
                expect(options.limit).toBeDefined();
            });
        });

        describe('CaptureVideoOptions', function () {
            it('capture.spec.8 CaptureVideoOptions constructor should exist', function () {
                var options = new CaptureVideoOptions();
                expect(options).toBeDefined();
                expect(options.limit).toBeDefined();
                expect(options.duration).toBeDefined();
            });
        });

        describe('CaptureError interface', function () {
            it('capture.spec.9 CaptureError constants should be defined', function () {
                expect(CaptureError.CAPTURE_INTERNAL_ERR).toBe(0);
                expect(CaptureError.CAPTURE_APPLICATION_BUSY).toBe(1);
                expect(CaptureError.CAPTURE_INVALID_ARGUMENT).toBe(2);
                expect(CaptureError.CAPTURE_NO_MEDIA_FILES).toBe(3);
            });

            it('capture.spec.10 CaptureError properties should exist', function () {
                var error = new CaptureError();
                expect(error).toBeDefined();
                expect(error.code).toBeDefined();
            });
        });

        describe('MediaFileData', function () {
            it('capture.spec.11 MediaFileData constructor should exist', function () {
                var fileData = new MediaFileData();
                expect(fileData).toBeDefined();
                expect(fileData.bitrate).toBeDefined();
                expect(fileData.codecs).toBeDefined();
                expect(fileData.duration).toBeDefined();
                expect(fileData.height).toBeDefined();
                expect(fileData.width).toBeDefined();
            });
        });

        describe('MediaFile', function () {
            it('capture.spec.12 MediaFile constructor should exist', function () {
                var fileData = new MediaFile();
                expect(fileData).toBeDefined();
                expect(fileData.name).toBeDefined();
                expect(fileData.type).toBeDefined();
                expect(fileData.lastModifiedDate).toBeDefined();
                expect(fileData.size).toBeDefined();
            });
        });
    });
};

/******************************************************************************/
/******************************************************************************/
/******************************************************************************/

exports.defineManualTests = function (contentEl, createActionButton) {
    var pageStartTime = +new Date();

    function log (value) {
        document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
        console.log(value);
    }

    function captureAudioWin (mediaFiles) {
        var path = mediaFiles[0].fullPath;
        log('Audio captured: ' + path);
        var m = new Media(path);
        m.play();
        getFileMetadata(mediaFiles[0]);
    }

    function captureAudioFail (e) {
        log('Error getting audio: ' + e.code);
    }

    function getAudio () {
        clearStatus();
        var options = { limit: 1, duration: 10 };
        navigator.device.capture.captureAudio(captureAudioWin, captureAudioFail, options);
    }

    function captureImageWin (mediaFiles) {
        var path = mediaFiles[0].fullPath;
        // Necessary since windows doesn't allow file URLs for <img> elements
        if (cordova.platformId === 'windows' || cordova.platformId === 'windows8' || cordova.platformId === 'browser') {
            // eslint-disable-line no-undef
            path = mediaFiles[0].localURL;
        }
        log('Image captured: ' + path);
        document.getElementById('camera_image').src = path;
    }

    function captureImagesWin (mediaFiles) {
        var path = mediaFiles[0].fullPath;
        // Necessary since windows doesn't allow file URLs for <img> elements
        if (cordova.platformId === 'windows' || cordova.platformId === 'windows8' || cordova.platformId === 'browser') {
            // eslint-disable-line no-undef
            path = mediaFiles[0].localURL;
        }
        var path2 = mediaFiles[1].fullPath;
        // Necessary since windows doesn't allow file URLs for <img> elements
        if (cordova.platformId === 'windows' || cordova.platformId === 'windows8' || cordova.platformId === 'browser') {
            // eslint-disable-line no-undef
            path = mediaFiles[1].localURL;
        }
        var path3 = mediaFiles[2].fullPath;
        // Necessary since windows doesn't allow file URLs for <img> elements
        if (cordova.platformId === 'windows' || cordova.platformId === 'windows8' || cordova.platformId === 'browser') {
            // eslint-disable-line no-undef
            path = mediaFiles[2].localURL;
        }
        log('Image captured: ' + path);
        log('Image captured: ' + path2);
        log('Image captured: ' + path3);
        document.getElementById('camera_image').src = path;
        document.getElementById('camera_image2').src = path2;
        document.getElementById('camera_image3').src = path3;
    }

    function captureImageFail (e) {
        log('Error getting image: ' + e.code);
    }

    function getImage () {
        clearStatus();
        var options = { limit: 1 };
        navigator.device.capture.captureImage(captureImageWin, captureImageFail, options);
    }

    function getImages () {
        clearStatus();
        var options = { limit: 3 };
        navigator.device.capture.captureImage(captureImagesWin, captureImageFail, options);
    }

    function captureVideoWin (mediaFiles) {
        var path = mediaFiles[0].fullPath;
        log('Video captured: ' + path);

        // need to inject the video element into the html
        // doesn't seem to work if you have a pre-existing video element and
        // add in a source tag
        var vid = document.createElement('video');
        vid.id = 'theVideo';
        vid.width = '320';
        vid.height = '240';
        vid.controls = 'true';
        var source_vid = document.createElement('source');
        source_vid.id = 'theSource';
        source_vid.src = path;
        vid.appendChild(source_vid);
        document.getElementById('video_container').appendChild(vid);
        getFileMetadata(mediaFiles[0]);
    }

    function getFileMetadata (mediaFile) {
        mediaFile.getFormatData(getMetadataWin, getMetadataFail);
    }

    function getMetadataWin (metadata) {
        var strMetadata = 'duration = ' + metadata.duration + '\n' + 'width = ' + metadata.width + '\n' + 'height = ' + metadata.height;
        log(strMetadata);
    }

    function getMetadataFail (e) {
        log('Error getting metadata: ' + e.code);
    }

    function captureVideoFail (e) {
        log('Error getting video: ' + e.code);
    }

    function getVideo () {
        clearStatus();
        var options = { limit: 1, duration: 10 };
        navigator.device.capture.captureVideo(captureVideoWin, captureVideoFail, options);
    }

    function permissionWasNotAllowed () {
        log('Media has been captured. Have you forgotten to disallow camera for this app?');
    }

    function catchPermissionError (error) {
        if (CaptureError.CAPTURE_PERMISSION_DENIED === error.code) {
            log('Sucess: permission error has been detected!');
        } else {
            log('Error: another error with code: ' + error.code);
        }
    }

    function getVideoPermissionError () {
        var options = { limit: 1, duration: 10 };
        navigator.device.capture.captureVideo(permissionWasNotAllowed, catchPermissionError, options);
    }

    function getImagePermissionError () {
        var options = { limit: 1 };
        navigator.device.capture.captureImage(permissionWasNotAllowed, catchPermissionError, options);
    }

    function resolveMediaFileURL (mediaFile, callback) {
        resolveLocalFileSystemURL(
            mediaFile.localURL,
            function (entry) {
                log('Resolved by URL: ' + mediaFile.localURL);
                if (callback) callback();
            },
            function (err) {
                log('Failed to resolve by URL: ' + mediaFile.localURL);
                log('Error: ' + JSON.stringify(err));
                if (callback) callback();
            }
        );
    }

    function resolveMediaFile (mediaFile, callback) {
        resolveLocalFileSystemURL(
            mediaFile.fullPath,
            function (entry) {
                log('Resolved by path: ' + mediaFile.fullPath);
                if (callback) callback();
            },
            function (err) {
                log('Failed to resolve by path: ' + mediaFile.fullPath);
                log('Error: ' + JSON.stringify(err));
                if (callback) callback();
            }
        );
    }

    function resolveVideo () {
        clearStatus();
        var options = { limit: 1, duration: 5 };
        navigator.device.capture.captureVideo(
            function (mediaFiles) {
                captureVideoWin(mediaFiles);
                resolveMediaFile(mediaFiles[0], function () {
                    resolveMediaFileURL(mediaFiles[0]);
                });
            },
            captureVideoFail,
            options
        );
    }

    function clearStatus () {
        document.getElementById('camera_status').innerHTML = '';
        document.getElementById('camera_image').src = 'about:blank';
        document.getElementById('camera_image2').src = 'about:blank';
        document.getElementById('camera_image3').src = 'about:blank';
    }

    /******************************************************************************/

    contentEl.innerHTML =
        '<div id="info" style="white-space: pre-wrap">' +
        '<b>Status:</b> <div id="camera_status"></div>' +
        'img1: <img width="100" id="camera_image">' +
        'img2: <img width="100" id="camera_image2">' +
        'img3: <img width="100" id="camera_image3">' +
        'video: <div id="video_container"></div>' +
        '</div><div id="audio"></div>' +
        'Expected result: Audio recorder will come up. Press record button to record for 10 seconds. Press Done. Status box will update with audio file and automatically play recording.' +
        '<p/> <div id="image"></div>' +
        'Expected result: Status box will update with image just taken.' +
        '<p/> <div id="images"></div>' +
        'Expected result: Status box will update with images just taken.' +
        '<p/> <div id="video"></div>' +
        'Expected result: Record 10 second video. Status box will update with video file that you can play.' +
        '<p/> <div id="video_and_resolve"></div>' +
        'Expected result: Record 5 second video. Status box will show that URL was resolved and video will get added at the bottom of the status box for playback.' +
        '<p/> <div id="prohibited_camera_video"></div>' +
        'Expected result (iOS only): camera picker and alert with message that camera access is prohibited are shown. The alert has 2 buttons: OK and Settings. By click on "OK" camera is hidden, by pressing Settings it shows privacy settings for the app' +
        '<p/> <div id="prohibited_camera_image"></div>' +
        'Expected result (iOS only): camera picker and alert with message that camera access is prohibited are shown. The alert has 2 buttons: OK and Settings. By click on "OK" camera is hidden, by pressing Settings it shows privacy settings for the app';

    createActionButton(
        'Capture 10 sec of audio and play',
        function () {
            getAudio();
        },
        'audio'
    );

    createActionButton(
        'Capture 1 image',
        function () {
            getImage();
        },
        'image'
    );

    createActionButton(
        'Capture 3 images',
        function () {
            getImages();
        },
        'images'
    );

    createActionButton(
        'Capture 10 sec of video',
        function () {
            getVideo();
        },
        'video'
    );

    createActionButton(
        'Capture 5 sec of video and resolve',
        function () {
            resolveVideo();
        },
        'video_and_resolve'
    );

    createActionButton(
        'Disable access to Camera and click to capture video',
        function () {
            getVideoPermissionError();
        },
        'prohibited_camera_video'
    );

    createActionButton(
        'Disable access to Camera and click to capture image',
        function () {
            getImagePermissionError();
        },
        'prohibited_camera_image'
    );
};
