<!DOCTYPE html>
<!--

 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.

-->


<html>
  <head>
    <meta name="viewport" content="width=device-width,height=device-height,user-scalable=no,maximum-scale=1.0,initial-scale=1.0" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <!-- ISO-8859-1 -->
    <title>Cordova Mobile Spec</title>
    <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8">
    <script type="text/javascript" charset="utf-8" src="../cordova-incl.js"></script>


<script type="text/javascript" charset="utf-8">

    var deviceReady = false;
    var platformId = cordova.require('cordova/platform').id;
    var pictureUrl = null;
    var fileObj = null;
    var fileEntry = null;
    var pageStartTime = +new Date();
    
    //default camera options
    var camQualityDefault = ['quality value', 50];
    var camDestinationTypeDefault = ['FILE_URI', 1];
    var camPictureSourceTypeDefault = ['CAMERA', 1];
    var camAllowEditDefault = ['allowEdit', false];
    var camEncodingTypeDefault = ['JPEG', 0];
    var camMediaTypeDefault = ['mediaType', 0];
    var camCorrectOrientationDefault = ['correctOrientation', false];
    var camSaveToPhotoAlbumDefault = ['saveToPhotoAlbum', true];
    

    //-------------------------------------------------------------------------
    // Camera
    //-------------------------------------------------------------------------

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

    function clearStatus() {
        document.getElementById('camera_status').innerHTML = '';
        document.getElementById('camera_image').src = 'about:blank';
        var canvas = document.getElementById('canvas');
        canvas.width = canvas.height = 1;
        pictureUrl = null;
        fileObj = null;
        fileEntry = null;
    }

    function setPicture(url, callback) {
		try {
			window.atob(url);
			// if we got here it is a base64 string (DATA_URL)
			url = "data:image/jpeg;base64," + url;
		} catch (e) {
			// not DATA_URL
		    log('URL: ' + url.slice(0, 100));
		}    
    
        pictureUrl = url;
        var img = document.getElementById('camera_image');
        var startTime = new Date();
        img.src = url;
        img.onloadend = function() {
            log('Image tag load time: ' + (new Date() - startTime));
            callback && callback();
        };
    }

    function onGetPictureError(e) {
        log('Error getting picture: ' + e.code);
    }

    function getPictureWin(data) {
        setPicture(data);
        // TODO: Fix resolveLocalFileSystemURI to work with native-uri.
        if (pictureUrl.indexOf('file:') == 0 || pictureUrl.indexOf('content:') == 0) {
            resolveLocalFileSystemURI(data, function(e) {
                fileEntry = e;
                logCallback('resolveLocalFileSystemURI()', true)(e.toURL());
            }, logCallback('resolveLocalFileSystemURI()', false));
        } else if (pictureUrl.indexOf('data:image/jpeg;base64' == 0)) {
        	// do nothing
        } else {
            var path = pictureUrl.replace(/^file:\/\/(localhost)?/, '').replace(/%20/g, ' ');
            fileEntry = new FileEntry('image_name.png', path);
        }
    }

    function getPicture() {
        clearStatus();
        var options = extractOptions();
        log('Getting picture with options: ' + JSON.stringify(options));
        var popoverHandle = navigator.camera.getPicture(getPictureWin, onGetPictureError, options);

        // Reposition the popover if the orientation changes.
        window.onorientationchange = function() {
            var newPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, 0);
            popoverHandle.setPosition(newPopoverOptions);
        }
    }

    function uploadImage() {
        var ft = new FileTransfer(),
            uploadcomplete=0,
            progress = 0,
            options = new FileUploadOptions();
        options.fileKey="photo";
        options.fileName='test.jpg';
        options.mimeType="image/jpeg";
        ft.onprogress = function(progressEvent) {
            log('progress: ' + progressEvent.loaded + ' of ' + progressEvent.total);
        };
        var server = "http://cordova-filetransfer.jitsu.com";

        ft.upload(pictureUrl, server + '/upload', win, fail, options);
        function win(information_back){
            log('upload complete');
        }
        function fail(message) {
            log('upload failed: ' + JSON.stringify(message));
        }
    }

    function logCallback(apiName, success) {
        return function() {
            log('Call to ' + apiName + (success ? ' success: ' : ' failed: ') + JSON.stringify([].slice.call(arguments)));
        };
    }

    /**
     * Select image from library using a NATIVE_URI destination type
     * This calls FileEntry.getMetadata, FileEntry.setMetadata, FileEntry.getParent, FileEntry.file, and FileReader.readAsDataURL.
     */
    function readFile() {
        function onFileReadAsDataURL(evt) {
            var img = document.getElementById('camera_image');
            img.style.visibility = "visible";
            img.style.display = "block";
            img.src = evt.target.result;
            log("FileReader.readAsDataURL success");
        };

        function onFileReceived(file) {
            log('Got file: ' + JSON.stringify(file));
            fileObj = file;

            var reader = new FileReader();
            reader.onload = function() {
                log('FileReader.readAsDataURL() - length = ' + reader.result.length);
            };
            reader.onerror = logCallback('FileReader.readAsDataURL', false);
            reader.readAsDataURL(file);
        };
        // Test out onFileReceived when the file object was set via a native <input> elements.
        if (fileObj) {
            onFileReceived(fileObj);
        } else {
            fileEntry.file(onFileReceived, logCallback('FileEntry.file', false));
        }
    }
    function getFileInfo() {
        // Test FileEntry API here.
        fileEntry.getMetadata(logCallback('FileEntry.getMetadata', true), logCallback('FileEntry.getMetadata', false));
        fileEntry.setMetadata(logCallback('FileEntry.setMetadata', true), logCallback('FileEntry.setMetadata', false), { "com.apple.MobileBackup": 1 });
        fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
        fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
    };

    /**
     * Copy image from library using a NATIVE_URI destination type
     * This calls FileEntry.copyTo and FileEntry.moveTo.
     */
    function copyImage() {
        var onFileSystemReceived = function(fileSystem) {
            var destDirEntry = fileSystem.root;

            // Test FileEntry API here.
            fileEntry.copyTo(destDirEntry, 'copied_file.png', logCallback('FileEntry.copyTo', true), logCallback('FileEntry.copyTo', false));
            fileEntry.moveTo(destDirEntry, 'moved_file.png', logCallback('FileEntry.moveTo', true), logCallback('FileEntry.moveTo', false));
        };

        window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, onFileSystemReceived, null);
    };

    /**
     * Write image to library using a NATIVE_URI destination type
     * This calls FileEntry.createWriter, FileWriter.write, and FileWriter.truncate.
     */
    function writeImage() {
        var onFileWriterReceived = function(fileWriter) {
            fileWriter.onwrite = logCallback('FileWriter.write', true);
            fileWriter.onerror = logCallback('FileWriter.write', false);
            fileWriter.write("some text!");
        };

        var onFileTruncateWriterReceived = function(fileWriter) {
            fileWriter.onwrite = logCallback('FileWriter.truncate', true);
            fileWriter.onerror = logCallback('FileWriter.truncate', false);
            fileWriter.truncate(10);
        };

        fileEntry.createWriter(onFileWriterReceived, logCallback('FileEntry.createWriter', false));
        fileEntry.createWriter(onFileTruncateWriterReceived, null);
    };

    function displayImageUsingCanvas() {
        var canvas = document.getElementById('canvas');
        var img = document.getElementById('camera_image');
        var w = img.width;
        var h = img.height;
        h = 100 / w * h;
        w = 100;
        canvas.width = w;
        canvas.height= h;
        var context = canvas.getContext('2d');
        context.drawImage(img, 0, 0, w, h);
    };

    /**
     * Remove image from library using a NATIVE_URI destination type
     * This calls FileEntry.remove.
     */
    function removeImage() {
        fileEntry.remove(logCallback('FileEntry.remove', true), logCallback('FileEntry.remove', false));
    };

    function testInputTag(inputEl) {
        clearStatus();
        // iOS 6 likes to dead-lock in the onchange context if you
        // do any alerts or try to remote-debug.
        window.setTimeout(function() {
            testNativeFile2(inputEl);
        }, 0);
    };

    function testNativeFile2(inputEl) {
        if (!inputEl.value) {
            alert('No file selected.');
            return;
        }
        fileObj = inputEl.files[0];
        if (!fileObj) {
            alert('Got value but no file.');
            return;
        }
        var URLApi = window.URL || window.webkitURL;
        if (URLApi) {
            var blobURL = URLApi.createObjectURL(fileObj);
            if (blobURL) {
                setPicture(blobURL, function() {
                    URLApi.revokeObjectURL(blobURL);
                });
            } else {
                log('URL.createObjectURL returned null');
            }
        } else {
            log('URL.createObjectURL() not supported.');
        }
    }

    function extractOptions() {
        var els = document.querySelectorAll('#image-options select');
        var ret = {};
        for (var i = 0, el; el = els[i]; ++i) {
            var value = el.value;
            if (value === '') continue;
            if (el.isBool) {
                ret[el.keyName] = !!+value;
            } else {
                ret[el.keyName] = +value;
            }
        }
        return ret;
    }

    function createOptionsEl(name, values, selectionDefault) {
        var container = document.createElement('div');
        container.style.display = 'inline-block';
        container.appendChild(document.createTextNode(name + ': '));
        var select = document.createElement('select');
        select.keyName = name;
        container.appendChild(select);
        
        // if we didn't get a default value, insert the blank <default> entry
        if (selectionDefault == undefined) {
            var opt = document.createElement('option');
            opt.value = '';
            opt.text = '<default>';
            select.appendChild(opt);
        }
        
        select.isBool = typeof values == 'boolean';
        if (select.isBool) {
            values = {'true': 1, 'false': 0};
        }
        
        for (var k in values) {
            var opt = document.createElement('option');
            opt.value = values[k];
            opt.textContent = k;
            if (selectionDefault) {
                if (selectionDefault[0] == k) {
                    opt.selected = true;
                }
            }
            select.appendChild(opt);
        }
        var optionsDiv = document.getElementById('image-options');
        optionsDiv.appendChild(container);
    }

    /**
     * Function called when page has finished loading.
     */
    function init() {
        document.addEventListener("deviceready", function() {
            deviceReady = true;
            console.log("Device="+device.platform+" "+device.version);
            createOptionsEl('sourceType', Camera.PictureSourceType, camPictureSourceTypeDefault);
            createOptionsEl('destinationType', Camera.DestinationType, camDestinationTypeDefault);
            createOptionsEl('encodingType', Camera.EncodingType, camEncodingTypeDefault);
            createOptionsEl('mediaType', Camera.MediaType, camMediaTypeDefault);
            createOptionsEl('quality', {'0': 0, '50': 50, '80': 80, '100': 100}, camQualityDefault);
            createOptionsEl('targetWidth', {'50': 50, '200': 200, '800': 800, '2048': 2048});
            createOptionsEl('targetHeight', {'50': 50, '200': 200, '800': 800, '2048': 2048});
            createOptionsEl('allowEdit', true, camAllowEditDefault);
            createOptionsEl('correctOrientation', true, camCorrectOrientationDefault);
            createOptionsEl('saveToPhotoAlbum', true, camSaveToPhotoAlbumDefault);
            createOptionsEl('cameraDirection', Camera.Direction);
                          
        }, false);
        window.setTimeout(function() {
            if (!deviceReady) {
                alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
            }
        },1000);
    };

</script>

  </head>
  <body onload="init();" id="stage" class="theme">

    <h1>Camera</h1>
    <div id="info" style="white-space: pre-wrap">
        <b>Status:</b> <div id="camera_status"></div>
        img: <img width="100" id="camera_image">
        canvas: <canvas id="canvas" width="1" height="1"></canvas>
    </div>
    <h2>Cordova Camera API</h2>
    <div id="image-options"></div>
    <div class="btn large" onclick="getPicture();">camera.getPicture()</div>
    <h2>Native File Inputs</h2>
    <div>input type=file <input type="file" onchange="testInputTag(this)"></div>
    <div>capture=camera <input type="file" accept="image/*;capture=camera" onchange="testInputTag(this)"></div>
    <div>capture=camcorder <input type="file" accept="video/*;capture=camcorder" onchange="testInputTag(this)"></div>
    <div>capture=microphone <input type="file" accept="audio/*;capture=microphone" onchange="testInputTag(this)"></div>
    <h2>Actions</h2>
    <div class="btn large" onclick="getFileInfo();">Get File Metadata</div>
    <div class="btn large" onclick="readFile();">Read with FileReader</div>
    <div class="btn large" onclick="copyImage();">Copy Image</div>
    <div class="btn large" onclick="writeImage();">Write Image</div>
    <div class="btn large" onclick="uploadImage();">Upload Image</div>
    <div class="btn large" onclick="displayImageUsingCanvas();">Draw Using Canvas</div>
    <div class="btn large" onclick="removeImage();">Remove Image</div>
    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
  </body>
</html>
