<!-- 

/***********************************************************************************************************
 * Prime
 * Name         : SubUploadUtilRemoteVFPage
 * Created By   : Prime Team
 * Purpose      : VF page for Sub upload Util - file upload
 * Created Date : 30 Nov 2017
 *
 * Date Modified                Modified By             Description of the update
  ----------------------------------------------------------------------------------------------------------
 * 
 **********************************************************************************************************/

-->

<apex:page controller="SubUploadUtilRemoteController">
    <script type="text/javascript">
        /* constants across all the function calls */
        const CHUNK_SIZE = 950000;         // Maximum JavaScript Remoting message size is 1,000,000 characters
        const FILE_SIZE_IN_LINES = 3000;
        var noOfAttachments = 0;
        var uploadedAttachments = 0;
        var fileUploadFlag = null;

        var url = window.location.href;

        var urlSplit = url.split("=")

        var reqStr = urlSplit[1];
        var recordId = reqStr.substr(0, 15);

        function checkfile(sender) {
            var validExts = new Array(".csv");
            var fileExt = sender.value;
            fileExt = fileExt.substring(fileExt.lastIndexOf('.'));
            if (validExts.indexOf(fileExt) < 0) {
                alert("Invalid file type selected, valid only " + validExts.toString() + " file type.");
                location.reload();
                return false;
            } else
                return true;
        }

        function submit() {
            document.getElementsByClassName("spinner")[0].style = "display: block";
            Visualforce.remoting.Manager.invokeAction(
                '{!$RemoteAction.SubUploadUtilRemoteController.deletePreviousAttachments}',
                '{!$CurrentPage.parameters.ParentId}',
                function (result, event) {
                    var files = document.getElementById("inputFiles").files;
                    processFile(files[0]);
                },
                { escape: false }
            );
        }

        /* It reads the file uploaded and divide into chunks of FILE_SIZE_IN_LINES, and initiates the worker threads to process asynchronously */
        function processFile(file) {
            var fileReader = new FileReader();
            fileReader.onloadend = function (event) {
                var payloadCSV = this.result;
                var allTextLines = payloadCSV.split(/\r?\n/);
                var noOfLines = allTextLines.length - 1;
                var noOfFiles = Math.ceil(noOfLines / FILE_SIZE_IN_LINES);
                var smallerFiles = new Array();
                for (var i = 0, k = 1; i < noOfFiles; i++) {
                    var data = allTextLines[0] + "\r\n";

                    /* Check for header data same as in comma separated file */
                    //if (data !== "Email,Mailing List,Source,First Name,Last Name,Mobile Phone,Birthdate,Gender,Address 1,City,State,Country/Region,Postal Code,Preferred Language,Facebook Page,Twitter Handle,MyspaceId"+"\r\n") {
                    if (data !== "Email (Required),Opt-in (Required),Mailing List,File Source Description,Territory(2 digit ISO) (Required),Label (Required),First Name,Last Name,Mobile Phone,Birthdate (MM/DD/YYYY),Birthday (MM/DD) US ONLY,Gender,Address 1,City,State,Country/Region,Postal Code,Preferred Language,Facebook Page,Twitter Handle" + "\r\n") {
                        alert('Uploaded file is in incorrect format! Please upload the file in comma separated format.');
                        location.reload();
                        return false;
                    }

                    var tempdata = data;
                    for (var j = 0; j < FILE_SIZE_IN_LINES; j++) {
                        if (allTextLines[k] !== undefined) {
                            data = data + allTextLines[k] + "\r\n";
                        }
                        k++;
                    }
                    var b = new Blob([data], { type: "text/plain" });
                    //var b = new Blob([data],{type : "text/plain;charset=UTF-8"});
                    if (tempdata !== data) {
                        smallerFiles.push(b);
                    }
                }
                noOfAttachments = smallerFiles.length;
                for (var i = 0; i < smallerFiles.length; i++) {
                    fileUploadFlag = 'false';
                    var blobFile = smallerFiles[i];
                    /* important to assign to a separate 
                     function to avoid concurrency issues across threads. */
                    var fileName = file.name;
                    fileName = fileName.slice(0, -4) + "" + (i + 1) + ".csv";
                    if (i + 1 === noOfAttachments) {
                        fileUploadFlag = 'true';
                    }
                    fileWorker(blobFile, fileName, fileUploadFlag);
                }
                document.getElementById("btnSubmit").disabled = true;
                //alert('File uploading is in progress, please wait until success message');
            }
            fileReader.onerror = function (event) {
                console.log("There was an error reading the file.  Please try again.");
            }
            fileReader.onabort = function (event) {
                console.log("There was an error reading the file.  Please try again.");
            }
            fileReader.readAsText(file);  //Read the body of the file

        }

        /* Parallel worker that reads each individual file using FileReader each individual file.
         * Call the recursive function to upload chunks of file along with meta data to track state. 
         */
        function fileWorker(file, fileName, fileUploadFlag) {
            var fileReader = new FileReader();
            fileReader.onloadend = function (event) {
                /* Base 64 encode the file before sending it */
                //var payload = window.btoa(this.result);  
                var payload = this.result;
                var positionIndex = 0;
                var parentId = recordId;
                var attachmentName = fileName;
                var attachmentId = null;
                var description = 'false';
                uploadChunk(parentId, attachmentId, attachmentName, payload, positionIndex, description, fileUploadFlag);
            }
            fileReader.onerror = function (event) {
                console.log("There was an error reading the file.  Please try again.");
            }
            fileReader.onabort = function (event) {
                console.log("There was an error reading the file.  Please try again.");
            }
            fileReader.readAsText(file);  //Read the body of the file

        }

        /* Uploads the attachment into salesforce.
         * @param parentId - parent id of the record the file should be added to, if invalid, the transaction fails.
         * @param attachmentId - attachment id of the payload, if null creates a new attachment for the parent.
         * @param attachmentName - file name of the uploaded file.
         * @param payload - base64 encoded payload
         * @param positionIndex - position of the processed payload (used to maintain state to chunkify the payload) 
         */
        function uploadChunk(parentId, attachmentId, attachmentName, payload, positionIndex, description, fileUploadFlag) {
            if (positionIndex < payload.length) {
                var chunkPayload = "";
                if (payload.length <= positionIndex + CHUNK_SIZE) {
                    chunkPayload = payload.substring(positionIndex);
                } else {
                    chunkPayload = payload.substring(positionIndex, positionIndex + CHUNK_SIZE);
                }
                Visualforce.remoting.Manager.invokeAction(
                    '{!$RemoteAction.SubUploadUtilRemoteController.processChunk}',
                    parentId, attachmentId, attachmentName, chunkPayload, description, fileUploadFlag,
                    function (result, event) {
                        if (event.type === 'exception') {
                            console.log("exception");
                            console.log(event);
                        } else if (event.status) {
                            console.log(event);
                            positionIndex += CHUNK_SIZE;
                            uploadChunk(parentId, result, attachmentName, payload, positionIndex, description, fileUploadFlag);
                        } else {
                            console.log(event.message);
                        }
                    },
                    { buffer: false, escape: true, timeout: 120000 }
                );
            } else {
                console.log("upload completed, file name: " + attachmentName);
                uploadedAttachments++;
                if (uploadedAttachments == noOfAttachments) {
                    document.getElementsByClassName("spinner")[0].style = "display: none";
                    alert('File uploaded successfully!');
                    window.top.location = '/'+parentId; 
                }
            }
        }

    </script>

    <apex:slds />
    <apex:sectionHeader title="EU File Upload" subtitle="File Upload" />
    <apex:pageMessages id="pageMessage" />
    <apex:pageBlock title="Upload a Attachment">
        

        <apex:pageBlockSection showHeader="false" columns="2" id="block1">

            <apex:pageBlockSectionItem>
                <apex:outputLabel value="File" />
                <input type="file" id="inputFiles" onchange="checkfile(this);" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem>
                <input type="button" id="btnSubmit" value="Submit" onclick="submit()" />
            </apex:pageBlockSectionItem>

        </apex:pageBlockSection>
    </apex:pageBlock>
    <div class="demo-only demo-only demo-only_viewport spinner" style="display: none">
        <div role="status" class="slds-spinner slds-spinner_medium">
            <span class="slds-assistive-text">Loading</span>
            <div class="slds-spinner__dot-a"></div>
            <div class="slds-spinner__dot-b"></div>
        </div>
    </div>
</apex:page>