// 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.
(function(cloudStack) {

    var diskofferingObjs, selectedDiskOfferingObj;

    cloudStack.sections.storage = {
        title: 'label.storage',
        id: 'storage',
        sectionSelect: {
            label: 'label.select-view'
        },
        sections: {
            /**
             * Volumes
             */
            volumes: {
                type: 'select',
                title: 'label.volumes',
                listView: {
                    id: 'volumes',
                    label: 'label.volumes',
                    preFilter: function(args) {
                        var hiddenFields = [];
                        if (isAdmin() != true)
                            hiddenFields.push('hypervisor');
                        return hiddenFields;
                    },
                    fields: {
                        name: {
                            label: 'label.name'
                        },
                        type: {
                            label: 'label.type'
                        },
                        hypervisor: {
                            label: 'label.hypervisor'
                        },
                        vmdisplayname: {
                            label: 'label.vm.display.name'
                        }
                    },

                    // List view actions
                    actions: {
                        // Add volume
                        add: {
                            label: 'label.add',

                            preFilter: function(args) {
                                return !args.context.instances;
                            },

                            messages: {
                                confirm: function(args) {
                                    return 'message.add.volume';
                                },
                                notification: function(args) {
                                    return 'label.add.volume';
                                }
                            },

                            createForm: {
                                title: 'label.add.volume',
                                desc: 'message.add.volume',
                                fields: {
                                    name: {
                                        docID: 'helpVolumeName',
                                        label: 'label.name'
                                    },
                                    availabilityZone: {
                                        label: 'label.availability.zone',
                                        docID: 'helpVolumeAvailabilityZone',
                                        select: function(args) {
                                            $.ajax({
                                                url: createURL("listZones&available=true"),
                                                dataType: "json",
                                                async: true,
                                                success: function(json) {
                                                    var zoneObjs = json.listzonesresponse.zone;
                                                    args.response.success({
                                                        descriptionField: 'name',
                                                        data: zoneObjs
                                                    });
                                                }
                                            });
                                        }
                                    },
                                    diskOffering: {
                                        label: 'label.disk.offering',
                                        docID: 'helpVolumeDiskOffering',
                                        select: function(args) {
                                            $.ajax({
                                                url: createURL("listDiskOfferings"),
                                                dataType: "json",
                                                async: false,
                                                success: function(json) {
                                                    diskofferingObjs = json.listdiskofferingsresponse.diskoffering;
                                                    var items = [];
                                                    $(diskofferingObjs).each(function() {
                                                        items.push({
                                                            id: this.id,
                                                            description: this.displaytext
                                                        });
                                                    });
                                                    args.response.success({
                                                        data: items
                                                    });
                                                }
                                            });

                                            args.$select.change(function() {
                                                var diskOfferingId = $(this).val();
                                                $(diskofferingObjs).each(function() {
                                                    if (this.id == diskOfferingId) {
                                                        selectedDiskOfferingObj = this;
                                                        return false; //break the $.each() loop
                                                    }
                                                });
                                                if (selectedDiskOfferingObj == null)
                                                    return;

                                                var $form = $(this).closest('form');
                                                var $diskSize = $form.find('.form-item[rel=diskSize]');
                                                if (selectedDiskOfferingObj.iscustomized == true) {
                                                    $diskSize.css('display', 'inline-block');
                                                } else {
                                                    $diskSize.hide();
                                                }
                                                var $minIops = $form.find('.form-item[rel=minIops]');
                                                var $maxIops = $form.find('.form-item[rel=maxIops]');
                                                if (selectedDiskOfferingObj.iscustomizediops == true) {
                                                    $minIops.css('display', 'inline-block');
                                                    $maxIops.css('display', 'inline-block');
                                                } else {
                                                    $minIops.hide();
                                                    $maxIops.hide();
                                                }
                                            });
                                        }
                                    }

                                    ,
                                    diskSize: {
                                        label: 'label.disk.size.gb',
                                        docID: 'helpVolumeSizeGb',
                                        validation: {
                                            required: true,
                                            number: true
                                        },
                                        isHidden: true
                                    },

                                    minIops: {
                                        label: 'label.disk.iops.min',
                                        validation: {
                                            required: false,
                                            number: true
                                        },
                                        isHidden: true
                                    },

                                    maxIops: {
                                        label: 'label.disk.iops.max',
                                        validation: {
                                            required: false,
                                            number: true
                                        },
                                        isHidden: true
                                    }

                                }
                            },

                            action: function(args) {
                                var data = {
                                    name: args.data.name,
                                    zoneId: args.data.availabilityZone,
                                    diskOfferingId: args.data.diskOffering
                                };

                                // if(thisDialog.find("#size_container").css("display") != "none") { //wait for Brian to include $form in args
                                if (selectedDiskOfferingObj.iscustomized == true) {
                                    $.extend(data, {
                                        size: args.data.diskSize
                                    });
                                }

                                if (selectedDiskOfferingObj.iscustomizediops == true) {
                                    if (args.data.minIops != "" && args.data.minIops > 0) {
                                        $.extend(data, {
                                            miniops: args.data.minIops
                                        });
                                    }

                                    if (args.data.maxIops != "" && args.data.maxIops > 0) {
                                        $.extend(data, {
                                            maxiops: args.data.maxIops
                                        });
                                    }
                                }

                                $.ajax({
                                    url: createURL('createVolume'),
                                    data: data,
                                    success: function(json) {
                                        var jid = json.createvolumeresponse.jobid;
                                        args.response.success({
                                            _custom: {
                                                jobId: jid,
                                                getUpdatedItem: function(json) {
                                                    return json.queryasyncjobresultresponse.jobresult.volume;
                                                },
                                                getActionFilter: function() {
                                                    return volumeActionfilter;
                                                }
                                            }
                                        });
                                    },
                                    error: function(json) {
                                        args.response.error(parseXMLHttpResponse(json));
                                    }
                                });
                            },

                            notification: {
                                poll: pollAsyncJobResult
                            }
                        },

                        viewMetrics: {
                            label: 'label.metrics',
                            isHeader: true,
                            addRow: false,
                            action: {
                                custom: cloudStack.uiCustom.metricsView({resource: 'volumes'})
                            },
                            messages: {
                                notification: function (args) {
                                    return 'label.metrics';
                                }
                            }
                        },

                        uploadVolume: {
                            isHeader: true,
                            label: 'label.upload',
                            preFilter: function(args) {
                                return !args.context.instances;
                            },
                            messages: {
                                notification: function() {
                                    return 'label.upload.volume.from.url';
                                }
                            },
                            createForm: {
                                title: 'label.upload.volume.from.url',
                                fields: {
                                    url: {
                                        label: 'label.url',
                                        docID: 'helpUploadVolumeURL',
                                        validation: {
                                            required: true
                                        }
                                    },
                                    name: {
                                        label: 'label.name',
                                        validation: {
                                            required: true
                                        },
                                        docID: 'helpUploadVolumeName'
                                    },
                                    availabilityZone: {
                                        label: 'label.availability.zone',
                                        docID: 'helpUploadVolumeZone',
                                        select: function(args) {
                                            $.ajax({
                                                url: createURL("listZones&available=true"),
                                                dataType: "json",
                                                async: true,
                                                success: function(json) {
                                                    var zoneObjs = json.listzonesresponse.zone;
                                                    args.response.success({
                                                        descriptionField: 'name',
                                                        data: zoneObjs
                                                    });
                                                }
                                            });
                                        }
                                    },
                                    format: {
                                        label: 'label.format',
                                        docID: 'helpUploadVolumeFormat',
                                        select: function(args) {
                                            var items = [];
                                            items.push({
                                                id: 'RAW',
                                                description: 'RAW'
                                            });
                                            items.push({
                                                id: 'VHD',
                                                description: 'VHD'
                                            });
                                            items.push({
                                                id: 'VHDX',
                                                description: 'VHDX'
                                            });
                                            items.push({
                                                id: 'OVA',
                                                description: 'OVA'
                                            });
                                            items.push({
                                                id: 'QCOW2',
                                                description: 'QCOW2'
                                            });
                                            args.response.success({
                                                data: items
                                            });
                                        }

                                    },
                                    diskOffering: {
                                        label: 'label.custom.disk.offering',
                                        docID: 'helpVolumeDiskOffering',
                                        select: function(args) {
                                            var diskofferingObjs;
                                            $.ajax({
                                                url: createURL("listDiskOfferings"),
                                                dataType: "json",
                                                async: false,
                                                success: function(json) {
                                                    diskofferingObjs = json.listdiskofferingsresponse.diskoffering;
                                                    var items = [{
                                                        id: '',
                                                        description: ''
                                                    }];
                                                    $(diskofferingObjs).each(function() {
                                                        if (this.iscustomized == true) {
                                                            items.push({
                                                                id: this.id,
                                                                description: this.displaytext
                                                            });
                                                        }
                                                    });
                                                    args.response.success({
                                                        data: items
                                                    });
                                                }
                                            });
                                        }
                                    },
                                    diskOffering: {
                                        label: 'label.custom.disk.offering',
                                        docID: 'helpVolumeDiskOffering',
                                        select: function(args) {
                                            var diskofferingObjs;
                                            $.ajax({
                                                url: createURL("listDiskOfferings"),
                                                dataType: "json",
                                                async: false,
                                                success: function(json) {
                                                    diskofferingObjs = json.listdiskofferingsresponse.diskoffering;
                                                    var items = [{
                                                        id: '',
                                                        description: ''
                                                    }];
                                                    $(diskofferingObjs).each(function() {
                                                        if (this.iscustomized == true) {
                                                            items.push({
                                                                id: this.id,
                                                                description: this.displaytext
                                                            });
                                                        }
                                                    });
                                                    args.response.success({
                                                        data: items
                                                    });
                                                }
                                            });
                                        }
                                    },
                                    checksum: {
                                        docID: 'helpUploadVolumeChecksum',
                                        label: 'label.md5.checksum'
                                    }
                                }
                            },

                            action: function(args) {
                                var data = {
                                    name: args.data.name,
                                    zoneId: args.data.availabilityZone,
                                    format: args.data.format,
                                    url: args.data.url
                                };

                                if (args.data.diskOffering != '' && args.data.diskOffering.length > 0) {
                                    $.extend(data, {
                                        diskofferingid: args.data.diskOffering
                                    });
                                }

                                if (args.data.checksum != null && args.data.checksum.length > 0) {
                                    $.extend(data, {
                                        checksum: args.data.checksum
                                    });
                                }

                                $.ajax({
                                    url: createURL('uploadVolume'),
                                    data: data,
                                    success: function(json) {
                                        var jid = json.uploadvolumeresponse.jobid;
                                        args.response.success({
                                            _custom: {
                                                jobId: jid,
                                                getUpdatedItem: function(json) {
                                                    return json.queryasyncjobresultresponse.jobresult.volume;
                                                },
                                                getActionFilter: function() {
                                                    return volumeActionfilter;
                                                }
                                            }
                                        });
                                    },
                                    error: function(json) {
                                        args.response.error(parseXMLHttpResponse(json));
                                    }
                                });
                            },

                            notification: {
                                poll: pollAsyncJobResult
                            }
                        },

                        uploadVolumefromLocal: {
                            isHeader: true,
                            label: 'label.upload.from.local',
                            preFilter: function(args) {
                                return !args.context.instances;
                            },
                            messages: {
                                notification: function() {
                                    return 'label.upload.volume.from.local';
                                }
                            },
                            createForm: {
                                title: 'label.upload.volume.from.local',
                                fileUpload: {
                                    getURL: function(args) {
                                        args.data = args.formData;

                                        var data = {
                                            name: args.data.name,
                                            zoneId: args.data.availabilityZone,
                                            format: args.data.format,
                                            url: args.data.url
                                        };

                                        if (args.data.checksum != null && args.data.checksum.length > 0) {
                                            $.extend(data, {
                                                checksum: args.data.checksum
                                            });
                                        }

                                        $.ajax({
                                            url: createURL('getUploadParamsForVolume'),
                                            data: data,
                                            async: false,
                                            success: function(json) {
                                                var uploadparams = json.postuploadvolumeresponse.getuploadparams; //son.postuploadvolumeresponse.getuploadparams is an object, not an array of object.
                                                var volumeId = uploadparams.id;

                                                args.response.success({
                                                    url: uploadparams.postURL,
                                                    ajaxPost: true,
                                                    data: {
                                                        'X-signature': uploadparams.signature,
                                                        'X-expires': uploadparams.expires,
                                                        'X-metadata': uploadparams.metadata
                                                    }
                                                });
                                            }
                                        });
                                    },
                                    postUpload: function(args) {
                                        if(args.error) {
                                            args.response.error(args.errorMsg);
                                        } else {
                                            cloudStack.dialog.notice({
                                                message: "This volume file has been uploaded. Please check its status at Stroage menu > Volumes > " + args.data.name + " > Status field."
                                            });
                                            args.response.success();
                                        }
                                    }
                                },
                                fields: {
                                    volumeFileUpload: {
                                        label: 'label.local.file',
                                        isFileUpload: true,
                                        validation: {
                                            required: true
                                        }
                                    },
                                    name: {
                                        label: 'label.name',
                                        validation: {
                                            required: true
                                        },
                                        docID: 'helpUploadVolumeName'
                                    },
                                    availabilityZone: {
                                        label: 'label.availability.zone',
                                        docID: 'helpUploadVolumeZone',
                                        select: function(args) {
                                            $.ajax({
                                                url: createURL("listZones&available=true"),
                                                dataType: "json",
                                                async: true,
                                                success: function(json) {
                                                    var zoneObjs = json.listzonesresponse.zone;
                                                    args.response.success({
                                                        descriptionField: 'name',
                                                        data: zoneObjs
                                                    });
                                                }
                                            });
                                        }
                                    },
                                    format: {
                                        label: 'label.format',
                                        docID: 'helpUploadVolumeFormat',
                                        select: function(args) {
                                            var items = [];
                                            items.push({
                                                id: 'RAW',
                                                description: 'RAW'
                                            });
                                            items.push({
                                                id: 'VHD',
                                                description: 'VHD'
                                            });
                                            items.push({
                                                id: 'VHDX',
                                                description: 'VHDX'
                                            });
                                            items.push({
                                                id: 'OVA',
                                                description: 'OVA'
                                            });
                                            items.push({
                                                id: 'QCOW2',
                                                description: 'QCOW2'
                                            });
                                            args.response.success({
                                                data: items
                                            });
                                        }
                                    },
                                    checksum: {
                                        docID: 'helpUploadVolumeChecksum',
                                        label: 'label.md5.checksum'
                                    }
                                }
                            },

                            action: function(args) {
                                return; //createForm.fileUpload.getURL() has executed the whole action. Therefore, nothing needs to be done here.
                            },

                            notification: {
                                poll: pollAsyncJobResult
                            }
                        }
                    },

                    advSearchFields: {
                        name: {
                            label: 'label.name'
                        },
                        zoneid: {
                            label: 'label.zone',
                            select: function(args) {
                                $.ajax({
                                    url: createURL('listZones'),
                                    data: {},
                                    success: function(json) {
                                        var zones = json.listzonesresponse.zone ? json.listzonesresponse.zone : [];

                                        args.response.success({
                                            data: $.map(zones, function(zone) {
                                                return {
                                                    id: zone.id,
                                                    description: zone.name
                                                };
                                            })
                                        });
                                    }
                                });
                            }
                        },

                        domainid: {
                            label: 'label.domain',
                            select: function(args) {
                                if (isAdmin() || isDomainAdmin()) {
                                    $.ajax({
                                        url: createURL('listDomains'),
                                        data: {
                                            listAll: true,
                                            details: 'min'
                                        },
                                        success: function(json) {
                                            var array1 = [{
                                                id: '',
                                                description: ''
                                            }];
                                            var domains = json.listdomainsresponse.domain;
                                            if (domains != null && domains.length > 0) {
                                                for (var i = 0; i < domains.length; i++) {
                                                    array1.push({
                                                        id: domains[i].id,
                                                        description: domains[i].path
                                                    });
                                                }
                                            }
                                            array1.sort(function(a, b) {
                                                return a.description.localeCompare(b.description);
                                            });
                                            args.response.success({
                                                data: array1
                                            });
                                        }
                                    });
                                } else {
                                    args.response.success({
                                        data: null
                                    });
                                }
                            },
                            isHidden: function(args) {
                                if (isAdmin() || isDomainAdmin())
                                    return false;
                                else
                                    return true;
                            }
                        },

                        account: {
                            label: 'label.account',
                            isHidden: function(args) {
                                if (isAdmin() || isDomainAdmin())
                                    return false;
                                else
                                    return true;
                            }
                        },

                        tagKey: {
                            label: 'label.tag.key'
                        },
                        tagValue: {
                            label: 'label.tag.value'
                        }
                    },

                    dataProvider: function(args) {
                        var data = {};
                        listViewDataProvider(args, data);

                        if (args.context != null) {
                            if ("instances" in args.context) {
                                $.extend(data, {
                                    virtualMachineId: args.context.instances[0].id
                                });
                            }
                            if ("primarystorages" in args.context) {
                                $.extend(data, {
                                    storageid: args.context.primarystorages[0].id
                                });
                            }
                        }

                        $.ajax({
                            url: createURL('listVolumes'),
                            data: data,
                            success: function(json) {
                                var items = json.listvolumesresponse.volume;
                                args.response.success({
                                    actionFilter: volumeActionfilter,
                                    data: items
                                });
                            },
                            error: function(XMLHttpResponse) {
                                cloudStack.dialog.notice({
                                    message: parseXMLHttpResponse(XMLHttpResponse)
                                });
                                args.response.error();
                             }
                        });
                    },

                    detailView: {
                        name: 'label.volume.details',
                        viewAll: {
                            path: 'storage.snapshots',
                            label: 'label.snapshots'
                        },
                        actions: {

                            migrateVolume: {
                                label: 'label.migrate.volume',
                                messages: {
                                    confirm: function(args) {
                                        return 'message.confirm.migrate.volume';
                                    },
                                    notification: function(args) {
                                        return 'label.volume.migrated';
                                    }
                                },

                                createForm: {
                                    title: 'label.migrate.volume',
                                    desc: '',
                                    fields: {
                                        storagePool: {
                                            label: 'label.storage.pool',
                                            validation: {
                                                required: true
                                            },
                                            select: function(args) {
                                                $.ajax({
                                                    url: createURL("findStoragePoolsForMigration&id=" + args.context.volumes[0].id),
                                                    dataType: "json",
                                                    async: true,
                                                    success: function(json) {
                                                        var pools = json.findstoragepoolsformigrationresponse.storagepool;
                                                        var items = [];
                                                        $(pools).each(function() {
                                                            items.push({
                                                                id: this.id,
                                                                description: this.name + " (" + (this.suitableformigration ? "Suitable" : "Not Suitable") + ")"
                                                            });
                                                        });
                                                        args.response.success({
                                                            data: items
                                                        });

                                                    }
                                                });
                                            }
                                        }
                                    }

                                },

                                action: function(args) {
                                    $.ajax({
                                        url: createURL("migrateVolume&livemigrate=true&storageid=" + args.data.storagePool + "&volumeid=" + args.context.volumes[0].id),
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.migratevolumeresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }

                            },

                            takeSnapshot: {
                                label: 'label.action.take.snapshot',
                                messages: {
                                    notification: function(args) {
                                        return 'label.action.take.snapshot';
                                    }
                                },
                                createForm: {
                                    title: 'label.action.take.snapshot',
                                    desc: 'message.action.take.snapshot',
                                    fields: {
                                        quiescevm: {
                                            label: 'label.quiesce.vm',
                                            isBoolean: true,
                                            isHidden: function(args) {
                                                if (args.context.volumes[0].quiescevm == true)
                                                    return false;
                                                        else
                                                    return true;
                                            }
                                        },
                                        name: {
                                            label: 'label.name'
                                        }
                                    }
                                },
                                action: function(args) {
                                    var data = {
                                        volumeId: args.context.volumes[0].id,
                                        quiescevm: (args.data.quiescevm == 'on' ? true: false)
                                    };
                                    if (args.data.name != null && args.data.name.length > 0) {
                                        $.extend(data, {
                                            name: args.data.name
                                        });
                                    }
                                    $.ajax({
                                        url: createURL("createSnapshot"),
                                        data: data,
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.createsnapshotresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid //take snapshot from a volume doesn't change any property in this volume. So, don't need to specify getUpdatedItem() to return updated volume. Besides, createSnapshot API doesn't return updated volume.
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },

                            recurringSnapshot: {
                                label: 'label.snapshot.schedule',
                                action: {
                                    custom: cloudStack.uiCustom.recurringSnapshots({
                                        desc: 'message.snapshot.schedule',
                                        dataProvider: function(args) {
                                            $.ajax({
                                                url: createURL('listSnapshotPolicies'),
                                                data: {
                                                    volumeid: args.context.volumes[0].id
                                                },
                                                async: true,
                                                dataType: 'json',
                                                success: function(data) {
                                                    args.response.success({
                                                        data: $.map(
                                                            data.listsnapshotpoliciesresponse.snapshotpolicy ? data.listsnapshotpoliciesresponse.snapshotpolicy : [],
                                                            function(snapshot, index) {
                                                                return {
                                                                    id: snapshot.id,
                                                                    type: snapshot.intervaltype,
                                                                    time: snapshot.intervaltype > 0 ? snapshot.schedule.split(':')[1] + ':' + snapshot.schedule.split(':')[0] : snapshot.schedule,
                                                                    timezone: snapshot.timezone,
                                                                    keep: snapshot.maxsnaps,
                                                                    'day-of-week': snapshot.intervaltype == 2 ? snapshot.schedule.split(':')[2] : null,
                                                                    'day-of-month': snapshot.intervaltype == 3 ? snapshot.schedule.split(':')[2] : null
                                                                };
                                                            }
                                                        )
                                                    });
                                                }
                                            });
                                        },
                                        actions: {
                                            add: function(args) {
                                                var snap = args.snapshot;

                                                var data = {
                                                    keep: snap.maxsnaps,
                                                    timezone: snap.timezone
                                                };

                                                var convertTime = function(minute, hour, meridiem, extra) {
                                                    var convertedHour = meridiem == 'PM' ?
                                                        (hour != 12 ? parseInt(hour) + 12 : 12) : (hour != 12 ? hour : '00');
                                                    var time = minute + ':' + convertedHour;
                                                    if (extra) time += ':' + extra;

                                                    return time;
                                                };

                                                switch (snap['snapshot-type']) {
                                                    case 'hourly': // Hourly
                                                        $.extend(data, {
                                                            schedule: snap.schedule
                                                        });
                                                        break;

                                                    case 'daily': // Daily
                                                        $.extend(data, {
                                                            schedule: convertTime(
                                                                snap['time-minute'],
                                                                snap['time-hour'],
                                                                snap['time-meridiem']
                                                            )
                                                        });
                                                        break;

                                                    case 'weekly': // Weekly
                                                        $.extend(data, {
                                                            schedule: convertTime(
                                                                snap['time-minute'],
                                                                snap['time-hour'],
                                                                snap['time-meridiem'],
                                                                snap['day-of-week']
                                                            )
                                                        });
                                                        break;

                                                    case 'monthly': // Monthly
                                                        $.extend(data, {
                                                            schedule: convertTime(
                                                                snap['time-minute'],
                                                                snap['time-hour'],
                                                                snap['time-meridiem'],
                                                                snap['day-of-month']
                                                            )
                                                        });
                                                        break;
                                                }

                                                $.ajax({
                                                    url: createURL('createSnapshotPolicy'),
                                                    data: {
                                                        volumeid: args.context.volumes[0].id,
                                                        intervaltype: snap['snapshot-type'],
                                                        maxsnaps: snap.maxsnaps,
                                                        schedule: data.schedule,
                                                        timezone: snap.timezone
                                                    },
                                                    dataType: 'json',
                                                    async: true,
                                                    success: function(successData) {
                                                        var snapshot = successData.createsnapshotpolicyresponse.snapshotpolicy;

                                                        args.response.success({
                                                            data: {
                                                                id: snapshot.id,
                                                                type: snapshot.intervaltype,
                                                                time: snapshot.intervaltype > 0 ? snapshot.schedule.split(':')[1] + ':' + snapshot.schedule.split(':')[0] : snapshot.schedule,
                                                                timezone: snapshot.timezone,
                                                                keep: snapshot.maxsnaps,
                                                                'day-of-week': snapshot.intervaltype == 2 ? snapshot.schedule.split(':')[2] : null,
                                                                'day-of-month': snapshot.intervaltype == 3 ? snapshot.schedule.split(':')[2] : null
                                                            }
                                                        });
                                                    }
                                                });
                                            },
                                            remove: function(args) {
                                                $.ajax({
                                                    url: createURL('deleteSnapshotPolicies'),
                                                    data: {
                                                        id: args.snapshot.id
                                                    },
                                                    dataType: 'json',
                                                    async: true,
                                                    success: function(data) {
                                                        args.response.success();
                                                    }
                                                });
                                            }
                                        },

                                        // Select data
                                        selects: {
                                            schedule: function(args) {
                                                var time = [];

                                                for (var i = 1; i <= 59; i++) {
                                                    time.push({
                                                        id: i,
                                                        name: i
                                                    });
                                                }

                                                args.response.success({
                                                    data: time
                                                });
                                            },
                                            timezone: function(args) {
                                                args.response.success({
                                                    data: $.map(timezoneMap, function(value, key) {
                                                        return {
                                                            id: key,
                                                            name: value
                                                        };
                                                    })
                                                });
                                            },
                                            'day-of-week': function(args) {
                                                args.response.success({
                                                    data: [{
                                                        id: 1,
                                                        name: 'label.sunday'
                                                    }, {
                                                        id: 2,
                                                        name: 'label.monday'
                                                    }, {
                                                        id: 3,
                                                        name: 'label.tuesday'
                                                    }, {
                                                        id: 4,
                                                        name: 'label.wednesday'
                                                    }, {
                                                        id: 5,
                                                        name: 'label.thursday'
                                                    }, {
                                                        id: 6,
                                                        name: 'label.friday'
                                                    }, {
                                                        id: 7,
                                                        name: 'label.saturday'
                                                    }]
                                                });
                                            },

                                            'day-of-month': function(args) {
                                                var time = [];

                                                for (var i = 1; i <= 28; i++) {
                                                    time.push({
                                                        id: i,
                                                        name: i
                                                    });
                                                }

                                                args.response.success({
                                                    data: time
                                                });
                                            },

                                            'time-hour': function(args) {
                                                var time = [];

                                                for (var i = 1; i <= 12; i++) {
                                                    time.push({
                                                        id: i,
                                                        name: i
                                                    });
                                                }

                                                args.response.success({
                                                    data: time
                                                });
                                            },

                                            'time-minute': function(args) {
                                                var time = [];

                                                for (var i = 0; i <= 59; i++) {
                                                    time.push({
                                                        id: i < 10 ? '0' + i : i,
                                                        name: i < 10 ? '0' + i : i
                                                    });
                                                }

                                                args.response.success({
                                                    data: time
                                                });
                                            },

                                            'time-meridiem': function(args) {
                                                args.response.success({
                                                    data: [{
                                                        id: 'AM',
                                                        name: 'AM'
                                                    }, {
                                                        id: 'PM',
                                                        name: 'PM'
                                                    }]
                                                });
                                            }
                                        }
                                    })
                                },
                                messages: {
                                    notification: function(args) {
                                        return 'label.snapshot.schedule';
                                    }
                                }
                            },

                            attachDisk: {
                                addRow: 'false',
                                label: 'label.action.attach.disk',
                                messages: {
                                    confirm: function(args) {
                                        return 'message.confirm.attach.disk';
                                    },
                                    notification: function(args) {
                                        return 'label.action.attach.disk';
                                    }
                                },
                                createForm: {
                                    title: 'label.action.attach.disk',
                                    desc: 'label.action.attach.disk',
                                    fields: {
                                        virtualMachineId: {
                                            label: 'label.instance',
                                            select: function(args) {
                                                var zoneid = args.context.volumes[0].zoneid;
                                                var items = [];
                                                var data;

                                                if (!args.context.projects) {
                                                    data = {
                                                        zoneid: zoneid,
                                                        domainid: args.context.volumes[0].domainid,
                                                        account: args.context.volumes[0].account
                                                    };
                                                } else {
                                                    data = {
                                                        zoneid: zoneid,
                                                        projectid: args.context.projects[0].id
                                                    };
                                                }

                                                if (args.context.volumes[0].hypervisor != null && args.context.volumes[0].hypervisor.length > 0 && args.context.volumes[0].hypervisor != 'None') {
                                                    data = $.extend(data, {
                                                        hypervisor: args.context.volumes[0].hypervisor
                                                    });
                                                }

                                                $(['Running', 'Stopped']).each(function() {
                                                    $.ajax({
                                                        url: createURL('listVirtualMachines'),
                                                        data: $.extend(data, {
                                                            state: this.toString()
                                                        }),
                                                        async: false,
                                                        success: function(json) {
                                                            var instanceObjs = json.listvirtualmachinesresponse.virtualmachine;
                                                            $(instanceObjs).each(function() {
                                                                items.push({
                                                                    id: this.id,
                                                                    description: this.displayname ? this.displayname : this.name
                                                                });
                                                            });
                                                        }
                                                    });
                                                });

                                                args.response.success({
                                                    data: items
                                                });
                                            }
                                        }
                                    }
                                },
                                action: function(args) {
                                    $.ajax({
                                        url: createURL("attachVolume&id=" + args.context.volumes[0].id + '&virtualMachineId=' + args.data.virtualMachineId),
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.attachvolumeresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid,
                                                    getUpdatedItem: function(json) {
                                                        return json.queryasyncjobresultresponse.jobresult.volume;
                                                    },
                                                    getActionFilter: function() {
                                                        return volumeActionfilter;
                                                    }
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },
                            detachDisk: {
                                label: 'label.action.detach.disk',
                                messages: {
                                    confirm: function(args) {
                                        return 'message.detach.disk';
                                    },
                                    notification: function(args) {
                                        return 'label.action.detach.disk';
                                    }
                                },
                                action: function(args) {
                                    $.ajax({
                                        url: createURL("detachVolume&id=" + args.context.volumes[0].id),
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.detachvolumeresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid,
                                                    getUpdatedItem: function(json) {
                                                        return {
                                                            virtualmachineid: null,
                                                            vmdisplayname: null
                                                        };
                                                    },
                                                    getActionFilter: function() {
                                                        return volumeActionfilter;
                                                    }
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },

                            downloadVolume: {
                                label: 'label.action.download.volume',
                                messages: {
                                    confirm: function(args) {
                                        return 'message.download.volume.confirm';
                                    },
                                    notification: function(args) {
                                        return 'label.action.download.volume';
                                    },
                                    complete: function(args) {
                                        var url = args.url;
                                        var htmlMsg = _l('message.download.volume');
                                        var htmlMsg2 = htmlMsg.replace(/#/, url).replace(/00000/, url);
                                        //$infoContainer.find("#info").html(htmlMsg2);
                                        return htmlMsg2;
                                    }
                                },
                                action: function(args) {
                                    $.ajax({
                                        url: createURL("extractVolume&id=" + args.context.volumes[0].id + "&zoneid=" + args.context.volumes[0].zoneid + "&mode=HTTP_DOWNLOAD"),
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.extractvolumeresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid,
                                                    getUpdatedItem: function(json) {
                                                        return json.queryasyncjobresultresponse.jobresult.volume;
                                                    },
                                                    getActionFilter: function() {
                                                        return volumeActionfilter;
                                                    }
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },

                            createTemplate: {
                                label: 'label.create.template',
                                messages: {
                                    confirm: function(args) {
                                        return 'message.create.template';
                                    },
                                    notification: function(args) {
                                        return 'label.create.template';
                                    }
                                },
                                createForm: {
                                    title: 'label.create.template',
                                    preFilter: cloudStack.preFilter.createTemplate,
                                    desc: '',
                                    preFilter: function(args) {
                                        if (args.context.volumes[0].hypervisor == "XenServer") {
                                            if (isAdmin()) {
                                                args.$form.find('.form-item[rel=xenserverToolsVersion61plus]').css('display', 'inline-block');
                                            }
                                        }
                                    },
                                    fields: {
                                        name: {
                                            label: 'label.name',
                                            validation: {
                                                required: true
                                            }
                                        },
                                        displayText: {
                                            label: 'label.description',
                                            validation: {
                                                required: true
                                            }
                                        },
                                        xenserverToolsVersion61plus: {
                                            label: 'label.xenserver.tools.version.61.plus',
                                            isBoolean: true,
                                            isChecked: function (args) {
                                                var b = false;
                                                var vmObj;
                                                $.ajax({
                                                    url: createURL("listVirtualMachines"),
                                                    data: {
                                                        id: args.context.volumes[0].virtualmachineid
                                                    },
                                                    async: false,
                                                    success: function(json) {
                                                        vmObj = json.listvirtualmachinesresponse.virtualmachine[0];
                                                    }
                                                });
                                                if (vmObj == undefined) { //e.g. VM has failed over
                                                    if (isAdmin()) {
                                                        $.ajax({
                                                            url: createURL('listConfigurations'),
                                                            data: {
                                                                name: 'xenserver.pvdriver.version'
                                                            },
                                                            async: false,
                                                            success: function (json) {
                                                                if (json.listconfigurationsresponse.configuration != null && json.listconfigurationsresponse.configuration[0].value == 'xenserver61') {
                                                                    b = true;
                                                                }
                                                            }
                                                        });
                                                    }
                                                } else {
                                                     if ('details' in vmObj && 'hypervisortoolsversion' in vmObj.details) {
                                                         if (vmObj.details.hypervisortoolsversion == 'xenserver61')
                                                             b = true;
                                                         else
                                                             b = false;
                                                     }
                                                }
                                                return b;
                                            },
                                            isHidden: true
                                        },
                                        osTypeId: {
                                            label: 'label.os.type',
                                            select: function(args) {
                                                $.ajax({
                                                    url: createURL("listOsTypes"),
                                                    dataType: "json",
                                                    async: true,
                                                    success: function(json) {
                                                        var ostypes = json.listostypesresponse.ostype;
                                                        var items = [];
                                                        $(ostypes).each(function() {
                                                            items.push({
                                                                id: this.id,
                                                                description: this.description
                                                            });
                                                        });
                                                        args.response.success({
                                                            data: items
                                                        });
                                                    }
                                                });
                                            }
                                        },
                                        isPublic: {
                                            label: 'label.public',
                                            isBoolean: true
                                        },
                                        isPasswordEnabled: {
                                            label: 'label.password.enabled',
                                            isBoolean: true
                                        },
                                        isFeatured: {
                                            label: 'label.featured',
                                            isBoolean: true
                                        },
                                        isdynamicallyscalable: {
                                            label: 'label.dynamically.scalable',
                                            isBoolean: true
                                        }
                                    }
                                },
                                action: function(args) {
                                    var data = {
                                        volumeId: args.context.volumes[0].id,
                                        name: args.data.name,
                                        displayText: args.data.displayText,
                                        osTypeId: args.data.osTypeId,
                                        isPublic: (args.data.isPublic == "on"),
                                        passwordEnabled: (args.data.isPasswordEnabled == "on"),
                                        isdynamicallyscalable: (args.data.isdynamicallyscalable == "on")

                                    };

                                    if (args.$form.find('.form-item[rel=isFeatured]').css("display") != "none") {
                                        $.extend(data, {
                                            isfeatured: (args.data.isFeatured == "on")
                                        });
                                    }

                                    //XenServer only (starts here)
                                    if (args.$form.find('.form-item[rel=xenserverToolsVersion61plus]').length > 0) {
                                        if (args.$form.find('.form-item[rel=xenserverToolsVersion61plus]').css("display") != "none") {
                                            $.extend(data, {
                                                'details[0].hypervisortoolsversion': (args.data.xenserverToolsVersion61plus == "on") ? "xenserver61" : "xenserver56"
                                            });
                                        }
                                    }
                                    //XenServer only (ends here)

                                    $.ajax({
                                        url: createURL('createTemplate'),
                                        data: data,
                                        success: function(json) {
                                            var jid = json.createtemplateresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid,
                                                    getUpdatedItem: function(json) {
                                                        return {}; //no properties in this volume needs to be updated
                                                    },
                                                    getActionFilter: function() {
                                                        return volumeActionfilter;
                                                    }
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },

                            migrateToAnotherStorage: {
                                label: 'label.migrate.volume.to.primary.storage',
                                messages: {
                                    confirm: function(args) {
                                        return 'message.migrate.volume';
                                    },
                                    notification: function(args) {
                                        return 'label.migrate.volume.to.primary.storage';
                                    }
                                },
                                createForm: {
                                    title: 'label.migrate.volume.to.primary.storage',
                                    desc: '',
                                    fields: {
                                        storageId: {
                                            label: 'label.primary.storage',
                                            validation: {
                                                required: true
                                            },
                                            select: function(args) {
                                                $.ajax({
                                                    url: createURL("listStoragePools&zoneid=" + args.context.volumes[0].zoneid),
                                                    dataType: "json",
                                                    async: true,
                                                    success: function(json) {
                                                        var pools = json.liststoragepoolsresponse.storagepool;
                                                        var items = [];
                                                        $(pools).each(function() {
                                                            items.push({
                                                                id: this.id,
                                                                description: this.name
                                                            });
                                                        });
                                                        args.response.success({
                                                            data: items
                                                        });
                                                    }
                                                });
                                            }
                                        }
                                    }
                                },
                                action: function(args) {
                                    $.ajax({
                                        url: createURL("migrateVolume&storageid=" + args.data.storageId + "&volumeid=" + args.context.volumes[0].id),
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.migratevolumeresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid,
                                                    getUpdatedItem: function(json) {
                                                        return json.queryasyncjobresultresponse.jobresult.volume;
                                                    },
                                                    getActionFilter: function() {
                                                        return volumeActionfilter;
                                                    }
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },

                            remove: {
                                label: 'label.action.delete.volume',
                                messages: {
                                    confirm: function(args) {
                                        return 'message.action.delete.volume';
                                    },
                                    notification: function(args) {
                                        return 'label.action.delete.volume';
                                    }
                                },
                                action: function(args) {
                                    $.ajax({
                                        url: createURL("deleteVolume&id=" + args.context.volumes[0].id),
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            args.response.success();
                                        }
                                    });
                                },
                                notification: {
                                    poll: function(args) {
                                        args.complete();
                                    }
                                }
                            },

                            resize: {
                                label: 'label.action.resize.volume',
                                messages: {
                                    notification: function(args) {
                                        return 'label.action.resize.volume';
                                    }
                                },
                                createForm: {
                                    title: 'label.action.resize.volume',
                                    preFilter: function(args) {
                                        if (args.context.volumes != null && args.context.volumes[0].type == 'ROOT') {
                                            args.$form.find('.form-item[rel=newdiskoffering]').hide();
                                        } else {
                                            args.$form.find('.form-item[rel=newsize]').hide();
                                        }
                                    },
                                    fields: {
                                        newdiskoffering: {
                                            label: 'label.resize.new.offering.id',
                                            select: function(args) {
                                                if (args.context.volumes != null && args.context.volumes[0].type == 'ROOT') {
                                                    args.response.success({
                                                        data: []
                                                    });
                                                    return;
                                                }

                                                $.ajax({
                                                    url: createURL("listDiskOfferings"),
                                                    dataType: "json",
                                                    success: function(json) {
                                                        diskofferingObjs = json.listdiskofferingsresponse.diskoffering;
                                                        var items = [];
                                                        $(diskofferingObjs).each(function() {
                                                            items.push({
                                                                id: this.id,
                                                                description: this.displaytext
                                                            });
                                                        });
                                                        args.response.success({
                                                            data: items
                                                        });
                                                    }
                                                });

                                                args.$select.change(function() {
                                                    var diskOfferingId = $(this).val();
                                                    $(diskofferingObjs).each(function() {
                                                        if (this.id == diskOfferingId) {
                                                            selectedDiskOfferingObj = this;
                                                            return false; //break the $.each() loop
                                                        }
                                                    });
                                                    if (selectedDiskOfferingObj == null)
                                                        return;

                                                    var $form = $(this).closest('form');

                                                    var $shrinkok = $form.find('.form-item[rel=shrinkok]');
                                                    //unit of args.context.volumes[0].size is "byte"
                                                    //unit of selectedDiskOfferingObj.disksize is "gigabyte" ("GB"), so transfer it into "byte" by multiply (1024 * 1024 * 1024)
                                                    if (args.context.volumes[0].size > selectedDiskOfferingObj.disksize * (1024 * 1024 * 1024)) { //if original disk size  > new disk size
                                                        $shrinkok.css('display', 'inline-block');
                                                    } else {
                                                        $shrinkok.hide();
                                                    }

                                                    var $newsize = $form.find('.form-item[rel=newsize]');
                                                    if (selectedDiskOfferingObj.iscustomized == true) {
                                                        $newsize.css('display', 'inline-block');
                                                    } else {
                                                        $newsize.hide();
                                                    }

                                                    var $minIops = $form.find('.form-item[rel=minIops]');
                                                    var $maxIops = $form.find('.form-item[rel=maxIops]');
                                                    if (selectedDiskOfferingObj.iscustomizediops == true) {
                                                        $minIops.css('display', 'inline-block');
                                                        $maxIops.css('display', 'inline-block');
                                                    } else {
                                                        $minIops.hide();
                                                        $maxIops.hide();
                                                    }
                                                });
                                            }
                                        },
                                        newsize: {
                                            label: 'label.resize.new.size',
                                            validation: {
                                                required: true,
                                                number: true
                                            }
                                        },
                                        shrinkok: {
                                            label: 'label.resize.shrink.ok',
                                            isBoolean: true,
                                            isChecked: false
                                        },
                                        minIops: {
                                            label: 'label.disk.iops.min',
                                            validation: {
                                                required: false,
                                                number: true
                                            },
                                            isHidden: true
                                        },
                                        maxIops: {
                                            label: 'label.disk.iops.max',
                                            validation: {
                                                required: false,
                                                number: true
                                            },
                                            isHidden: true
                                        }
                                    }
                                },
                                action: function(args) {
                                    var array1 = [];

                                    if(args.$form.find('.form-item[rel=shrinkok]').css("display") != "none") {
                                        array1.push("&shrinkok=" + (args.data.shrinkok == "on"));
                                    }

                                    var newDiskOffering = args.data.newdiskoffering;
                                    var newSize;
                                    if (selectedDiskOfferingObj == null || selectedDiskOfferingObj.iscustomized == true) {
                                        newSize = args.data.newsize;
                                    }
                                    if (newDiskOffering != null && newDiskOffering.length > 0) {
                                        array1.push("&diskofferingid=" + todb(newDiskOffering));
                                    }
                                    if (newSize != null && newSize.length > 0) {
                                        array1.push("&size=" + todb(newSize));
                                    }

                                    var minIops;
                                    var maxIops;

                                    if (selectedDiskOfferingObj != null && selectedDiskOfferingObj.iscustomizediops == true) {
                                        minIops = args.data.minIops;
                                        maxIops = args.data.maxIops;
                                    }

                                    if (minIops != null && minIops.length > 0) {
                                        array1.push("&miniops=" + todb(minIops));
                                    }

                                    if (maxIops != null && maxIops.length > 0) {
                                        array1.push("&maxiops=" + todb(maxIops));
                                    }

                                    $.ajax({
                                        url: createURL("resizeVolume&id=" + args.context.volumes[0].id + array1.join("")),
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.resizevolumeresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid,
                                                    getUpdatedItem: function(json) {
                                                        return json.queryasyncjobresultresponse.jobresult.volume;
                                                    },
                                                    getActionFilter: function() {
                                                        return volumeActionfilter;
                                                    }
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            }
                        },
                        tabs: {
                            details: {
                                title: 'label.details',

                                preFilter: function(args) {
                                    var hiddenFields;
                                    if (isAdmin()) {
                                        hiddenFields = [];
                                    } else {
                                        hiddenFields = ['storage', 'hypervisor'];
                                    }
                                    return hiddenFields;
                                },

                                fields: [{
                                    name: {
                                        label: 'label.name',
                                        isEditable: true
                                    }
                                }, {
                                    id: {
                                        label: 'label.id'
                                    },
                                    zonename: {
                                        label: 'label.zone'
                                    },
                                    state: {
                                        label: 'label.state',
                                        pollAgainIfValueIsIn: {
                                            'UploadNotStarted': 1
                                        },
                                        pollAgainFn: function(context) {
                                            var toClearInterval = false;
                                            $.ajax({
                                                url: createURL("listVolumes&id=" + context.volumes[0].id),
                                                dataType: "json",
                                                async: false,
                                                success: function(json) {
                                                    var jsonObj = json.listvolumesresponse.volume[0];
                                                    if (jsonObj.state != context.volumes[0].state) {
                                                        toClearInterval = true; //to clear interval
                                                    }
                                                }
                                            });
                                            return toClearInterval;
                                        }
                                    },
                                    status: {
                                        label: 'label.status'
                                    },
                                    diskofferingdisplaytext: {
                                        label: 'label.disk.offering'
                                    },
                                    type: {
                                        label: 'label.type'
                                    },
                                    storagetype: {
                                        label: 'label.storage.type'
                                    },
                                    provisioningtype: {
                                        label: 'label.disk.provisioningtype'
                                    },
                                    hypervisor: {
                                        label: 'label.hypervisor'
                                    },
                                    size: {
                                        label: 'label.size',
                                        converter: function(args) {
                                            if (args == null || args == 0)
                                                return "";
                                            else
                                                return cloudStack.converters.convertBytes(args);
                                        }
                                    },
                                    miniops: {
                                        label: 'label.disk.iops.min',
                                        converter: function(args) {
                                            if (args == null || args == 0)
                                                return "";
                                            else
                                                return args;
                                        }
                                    },
                                    maxiops: {
                                        label: 'label.disk.iops.max',
                                        converter: function(args) {
                                            if (args == null || args == 0)
                                                return "";
                                            else
                                                return args;
                                        }
                                    },
                                    virtualmachineid: {
                                        label: 'label.vm.id',
                                        converter: function(args) {
                                            if (args == null)
                                                return _l('state.detached');
                                            else
                                                return args;
                                        }
                                    },
                                    //vmname: { label: 'label.vm.name' },
                                    vmdisplayname: {
                                        label: 'label.vm.display.name'
                                    },
                                    vmstate: {
                                        label: 'label.vm.state'
                                    },
                                    deviceid: {
                                        label: 'label.device.id'
                                    },
                                    storage: {
                                        label: 'label.storage'
                                    },
                                    created: {
                                        label: 'label.created',
                                        converter: cloudStack.converters.toLocalDate
                                    },
                                    domain: {
                                        label: 'label.domain'
                                    },
                                    account: {
                                        label: 'label.account'
                                    }
                                }],

                                tags: cloudStack.api.tags({
                                    resourceType: 'Volume',
                                    contextId: 'volumes'
                                }),


                                dataProvider: function(args) {
                                    $.ajax({
                                        url: createURL("listVolumes&id=" + args.context.volumes[0].id),
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jsonObj = json.listvolumesresponse.volume[0];

                                            $(window).trigger('cloudStack.module.sharedFunctions.addExtraProperties', {
                                                obj: jsonObj,
                                                objType: "Volume"
                                            });

                                            args.response.success({
                                                actionFilter: volumeActionfilter,
                                                data: jsonObj
                                            });
                                        }
                                    });
                                }
                            }
                        }
                    }
                }
            },

            /**
             * Snapshots
             */
            snapshots: {
                type: 'select',
                title: 'label.snapshots',
                listView: {
                    id: 'snapshots',
                    label: 'label.snapshots',
                    fields: {
                        volumename: {
                            label: 'label.volume'
                        },
                        name: {
                            label: 'label.name'
                        },
                        intervaltype: {
                            label: 'label.interval.type'
                        },
                        created: {
                            label: 'label.created',
                            converter: cloudStack.converters.toLocalDate
                        },
                        state: {
                            label: 'label.state',
                            indicator: {
                                'BackedUp': 'on',
                                'Destroyed': 'off'
                            }
                        }
                    },

                    advSearchFields: {
                        name: {
                            label: 'label.name'
                        },

                        domainid: {
                            label: 'label.domain',
                            select: function(args) {
                                if (isAdmin() || isDomainAdmin()) {
                                    $.ajax({
                                        url: createURL('listDomains'),
                                        data: {
                                            listAll: true,
                                            details: 'min'
                                        },
                                        success: function(json) {
                                            var array1 = [{
                                                id: '',
                                                description: ''
                                            }];
                                            var domains = json.listdomainsresponse.domain;
                                            if (domains != null && domains.length > 0) {
                                                for (var i = 0; i < domains.length; i++) {
                                                    array1.push({
                                                        id: domains[i].id,
                                                        description: domains[i].path
                                                    });
                                                }
                                            }
                                            array1.sort(function(a, b) {
                                                return a.description.localeCompare(b.description);
                                            });
                                            args.response.success({
                                                data: array1
                                            });
                                        }
                                    });
                                } else {
                                    args.response.success({
                                        data: null
                                    });
                                }
                            },
                            isHidden: function(args) {
                                if (isAdmin() || isDomainAdmin())
                                    return false;
                                else
                                    return true;
                            }
                        },

                        account: {
                            label: 'label.account',
                            isHidden: function(args) {
                                if (isAdmin() || isDomainAdmin())
                                    return false;
                                else
                                    return true;
                            }
                        },
                        tagKey: {
                            label: 'label.tag.key'
                        },
                        tagValue: {
                            label: 'label.tag.value'
                        }
                    },

                    dataProvider: function(args) {
                        var data = {};
                        var instanceVolumeIds = [];
                        listViewDataProvider(args, data);

                        if (args.context != null) {
                            if ("volumes" in args.context) {
                                $.extend(data, {
                                    volumeid: args.context.volumes[0].id
                                });
                            } else if (args.context.instances) {
                                $.ajax({
                                    url: createURL('listVolumes'),
                                    data: {
                                        virtualmachineid: args.context.instances[0].id,
                                        listAll: true
                                    },
                                    async: false,
                                    success: function(json) {
                                        instanceVolumeIds = $.map(json.listvolumesresponse.volume, function(volume) {
                                            return volume.id;
                                        })
                                    }
                                });
                                data.volumeid = instanceVolumeIds.join(',');
                            }
                        }

                        $.ajax({
                            url: createURL('listSnapshots'),
                            data: data,
                            success: function(json) {
                                var items = json.listsnapshotsresponse.snapshot;
                                args.response.success({
                                    actionFilter: snapshotActionfilter,
                                    data: items
                                });
                            },
                            error: function(XMLHttpResponse) {
                                cloudStack.dialog.notice({
                                    message: parseXMLHttpResponse(XMLHttpResponse)
                                });
                                args.response.error();
                             }
                        });
                    },

                    detailView: {
                        name: 'Snapshot detail',
                        actions: {
                            createTemplate: {
                                label: 'label.create.template',
                                messages: {
                                    confirm: function(args) {
                                        return 'message.create.template';
                                    },
                                    notification: function(args) {
                                        return 'label.create.template';
                                    }
                                },
                                createForm: {
                                    title: 'label.create.template',
                                    desc: '',
                                    fields: {
                                        name: {
                                            label: 'label.name',
                                            validation: {
                                                required: true
                                            }
                                        },
                                        displayText: {
                                            label: 'label.description',
                                            validation: {
                                                required: true
                                            }
                                        },
                                        osTypeId: {
                                            label: 'label.os.type',
                                            select: function(args) {
                                                $.ajax({
                                                    url: createURL("listOsTypes"),
                                                    dataType: "json",
                                                    async: true,
                                                    success: function(json) {
                                                        var ostypes = json.listostypesresponse.ostype;
                                                        var items = [];
                                                        $(ostypes).each(function() {
                                                            items.push({
                                                                id: this.id,
                                                                description: this.description
                                                            });
                                                        });
                                                        args.response.success({
                                                            data: items
                                                        });
                                                    }
                                                });
                                            }
                                        },
                                        isPublic: {
                                            label: 'label.public',
                                            isBoolean: true
                                        },
                                        isPasswordEnabled: {
                                            label: 'label.password.enabled',
                                            isBoolean: true
                                        },
                                        isdynamicallyscalable: {
                                            label: 'label.dynamically.scalable',
                                            isBoolean: true
                                        }
                                    }
                                },
                                action: function(args) {
                                    var data = {
                                        snapshotid: args.context.snapshots[0].id,
                                        name: args.data.name,
                                        displayText: args.data.displayText,
                                        osTypeId: args.data.osTypeId,
                                        isPublic: (args.data.isPublic == "on"),
                                        passwordEnabled: (args.data.isPasswordEnabled == "on"),
                                        isdynamicallyscalable: (args.data.isdynamicallyscalable == "on")
                                    };

                                    $.ajax({
                                        url: createURL('createTemplate'),
                                        data: data,
                                        success: function(json) {
                                            var jid = json.createtemplateresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid,
                                                    getUpdatedItem: function(json) {
                                                        return {}; //nothing in this snapshot needs to be updated
                                                    },
                                                    getActionFilter: function() {
                                                        return snapshotActionfilter;
                                                    }
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },

                            createVolume: {
                                label: 'label.action.create.volume',
                                messages: {
                                    confirm: function(args) {
                                        return 'message.confirm.create.volume';
                                    },
                                    notification: function(args) {
                                        return 'label.action.create.volume';
                                    }
                                },
                                createForm: {
                                    title: 'label.action.create.volume',
                                    desc: '',
                                    preFilter: function(args) {
                                        if (g_regionsecondaryenabled == true) {
                                            args.$form.find('.form-item[rel=zoneid]').css('display', 'inline-block');
                                        } else {
                                            args.$form.find('.form-item[rel=zoneid]').hide();
                                        }
                                    },
                                    fields: {
                                        name: {
                                            label: 'label.name',
                                            validation: {
                                                required: true
                                            }
                                        },
                                        zoneid: {
                                            label: 'label.availability.zone',
                                            isHidden: true,
                                            select: function(args) {
                                                $.ajax({
                                                    url: createURL("listZones&available=true"),
                                                    dataType: "json",
                                                    async: true,
                                                    success: function(json) {
                                                        var zoneObjs = json.listzonesresponse.zone;
                                                        var items = [{
                                                            id: '',
                                                            description: ''
                                                        }];
                                                        if (zoneObjs != null) {
                                                            for (i = 0; i < zoneObjs.length; i++) {
                                                                items.push({
                                                                    id: zoneObjs[i].id,
                                                                    description: zoneObjs[i].name
                                                                });
                                                            }
                                                        }
                                                        args.response.success({
                                                            data: items
                                                        });
                                                    }
                                                });
                                            }
                                        }
                                    }
                                },
                                action: function(args) {
                                    var data = {
                                        snapshotid: args.context.snapshots[0].id,
                                        name: args.data.name
                                    };

                                    if (args.$form.find('.form-item[rel=zoneid]').css("display") != "none" && args.data.zoneid != '') {
                                        $.extend(data, {
                                            zoneId: args.data.zoneid
                                        });
                                    }

                                    $.ajax({
                                        url: createURL('createVolume'),
                                        data: data,
                                        success: function(json) {
                                            var jid = json.createvolumeresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid,
                                                    getUpdatedItem: function(json) {
                                                        return {}; //nothing in this snapshot needs to be updated
                                                    },
                                                    getActionFilter: function() {
                                                        return snapshotActionfilter;
                                                    }
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },

                            revertSnapshot: {
                                label: 'label.action.revert.snapshot',
                                messages: {
                                    confirm: function(args) {
                                        return 'message.action.revert.snapshot';
                                    },
                                    notification: function(args) {
                                        return 'label.action.revert.snapshot';
                                    }
                                },
                                action: function(args) {
                                    $.ajax({
                                        url: createURL("revertSnapshot&id="+args.context.snapshots[0].id),
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.revertsnapshotresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            },

                            remove: {
                                label: 'label.action.delete.snapshot',
                                messages: {
                                    confirm: function(args) {
                                        return 'message.action.delete.snapshot';
                                    },
                                    notification: function(args) {
                                        return 'label.action.delete.snapshot';
                                    }
                                },
                                action: function(args) {
                                    $.ajax({
                                        url: createURL("deleteSnapshot&id=" + args.context.snapshots[0].id),
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jid = json.deletesnapshotresponse.jobid;
                                            args.response.success({
                                                _custom: {
                                                    jobId: jid
                                                }
                                            });
                                        }
                                    });
                                },
                                notification: {
                                    poll: pollAsyncJobResult
                                }
                            }
                        },
                        tabs: {
                            details: {
                                title: 'label.details',
                                fields: [{
                                    name: {
                                        label: 'label.name'
                                    }
                                }, {
                                    id: {
                                        label: 'label.id'
                                    },
                                    volumename: {
                                        label: 'label.volume.name'
                                    },
                                    state: {
                                        label: 'label.state'
                                    },
                                    intervaltype: {
                                        label: 'label.interval.type'
                                    },
                                    domain: {
                                        label: 'label.domain'
                                    },
                                    account: {
                                        label: 'label.account'
                                    },
                                    created: {
                                        label: 'label.created',
                                        converter: cloudStack.converters.toLocalDate
                                    }
                                }],

                                tags: cloudStack.api.tags({
                                    resourceType: 'Snapshot',
                                    contextId: 'snapshots'
                                }),

                                dataProvider: function(args) {
                                    $.ajax({
                                        url: createURL("listSnapshots&id=" + args.context.snapshots[0].id),
                                        dataType: "json",
                                        async: true,
                                        success: function(json) {
                                            var jsonObj = json.listsnapshotsresponse.snapshot[0];
                                            args.response.success({
                                                actionFilter: snapshotActionfilter,
                                                data: jsonObj
                                            });
                                        }
                                    });
                                }
                            }
                        }
                    }
                }
            }
        }
    };


    var volumeActionfilter = cloudStack.actionFilter.volumeActionfilter = function(args) {
        var jsonObj = args.context.item;
        var allowedActions = [];


        if (jsonObj.state == 'Destroyed' || jsonObj.state == 'Migrating' || jsonObj.state == 'Uploading') {
            return [];
        }
        if (jsonObj.state == 'UploadError') {
            return ["remove"];
        }

        if (jsonObj.hypervisor != "Ovm" && jsonObj.state == "Ready") {
            if (jsonObj.hypervisor == 'KVM') {
                if (jsonObj.vmstate == 'Running') {
                    if (g_kvmsnapshotenabled == true) { //"kvm.snapshot.enabled" flag should be taken to account only when snapshot is being created for Running vm (CLOUDSTACK-4428)
                        allowedActions.push("takeSnapshot");
                        allowedActions.push("recurringSnapshot");
                    }
                } else {
                    allowedActions.push("takeSnapshot");
                    allowedActions.push("recurringSnapshot");
                }
            } else {
                allowedActions.push("takeSnapshot");
                allowedActions.push("recurringSnapshot");
            }
        }

        if (jsonObj.hypervisor == "KVM" || jsonObj.hypervisor == "XenServer" || jsonObj.hypervisor == "VMware") {
            if (jsonObj.state == "Ready" || jsonObj.state == "Allocated") {
                allowedActions.push("resize");
            }
        }

        if (jsonObj.state != "Allocated") {
            if ((jsonObj.vmstate == "Stopped" || jsonObj.virtualmachineid == null) && jsonObj.state == "Ready") {
                allowedActions.push("downloadVolume");
            }
        }

        if (jsonObj.type == "ROOT" || jsonObj.type == "DATADISK") {
            if (jsonObj.state == "Ready" && isAdmin() && jsonObj.virtualmachineid != null) {
                allowedActions.push("migrateVolume");
            }
        }

        if (jsonObj.state != "Creating") {
            if (jsonObj.type == "ROOT") {
                if (jsonObj.vmstate == "Stopped") {
                    allowedActions.push("createTemplate");
                }
            } else { //jsonObj.type == "DATADISK"
                if (jsonObj.virtualmachineid != null) {
                    if (jsonObj.vmstate == "Running" || jsonObj.vmstate == "Stopped" || jsonObj.vmstate == "Destroyed") {
                        allowedActions.push("detachDisk");
                    }
                } else { // Disk not attached
                    allowedActions.push("remove");
                    if (jsonObj.state == "Ready" && isAdmin() && jsonObj.storagetype == "shared") {
                        allowedActions.push("migrateToAnotherStorage");
                    }
                    allowedActions.push("attachDisk");
                }
            }
        }

        return allowedActions;
    };

    var snapshotActionfilter = cloudStack.actionFilter.snapshotActionfilter = function(args) {
        var jsonObj = args.context.item;

        if (jsonObj.state == 'Destroyed') {
            return [];
        }

        var allowedActions = [];
        if (jsonObj.state == "BackedUp") {
            allowedActions.push("createTemplate");
            allowedActions.push("createVolume");

            if (jsonObj.revertable) {
                allowedActions.push("revertSnapshot");
            }
        }
        allowedActions.push("remove");

        return allowedActions;
    }

})(cloudStack);
