<!--
    * 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.
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html dir="ltr">
    
    <head>
		<script type="text/javascript" src="../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true, debugAtAllCosts:false"></script>
		<script type="text/javascript" src="uploader.js" charset="utf-8"></script>
		<script type="text/javascript" src="admin.js" charset="utf-8"></script>
        <link rel="stylesheet" type="text/css" href="../dijit/themes/tundra/tundra.css">
		<link href="admin.css" rel="stylesheet">
        <style type="text/css">
            html, body { width: 100%; height: 100%; margin: 0; } 
			#borderContainerTwo
            { width: 100%; height: 100%; }
        </style>
		
		<script type="text/javascript">
			
			var d = { 
				identifier: 'name',
				label: 'name',
				items: [
					{ name:'Create New Album', type:'album' },
					{ name:'Upload Photo', type:'album' }
				]
			};
			
			var folders = new dojo.data.ItemFileReadStore({ data: d });

			var folderModel =  new dijit.tree.ForestStoreModel({
				store: folders, 
				query: { type: "album" },
				childrenAttrs: [ "children" ]
			});
							
							
		var gallery = new dojo.rpc.JsonService( "/photark/Gallery?smd" );
		
		function createAlbum(){
			var albumLabel = newAlbumForm.attr('value');
			console.log("albumLabel:"+albumLabel);	
			var albumName;
			for(var key in albumLabel){
				albumName = albumLabel[key];
				console.log("albumName:"+albumName);
			}
			console.log("albumName:"+albumName);
			gallery.addAlbum(albumName);
			dojo.byId('albumCreated').innerHTML = "Album Successfully Created:" + albumName;
			dojo.byId('albumName').value = "";
		}
		
		
		function populateSelect(){
			gallery.getAlbums().addCallback(gallery_getAlbumsResponse);
		}
		
		function gallery_getAlbumsResponse(albums, exception) {
		if(exception) {
			alert(exception.msg);
			return;
		}
		var select = dijit.byId('selectalbum');
		var options = new dojo.data.ItemFileWriteStore({data: {identifier: 'name', items:[]}});
		
     	for (var i=0; i < albums.length; i++) {
          options.newItem({name: albums[i].name});
     	}
		select.attr('store', options);
	}
		
    	</script>
    </head>
    
    <body class="tundra ">
    	<!-- Inline declaration for programmatically created "Upload Photo" -->
	<!-- Inline declaration for programmatically created "New Message" tabs -->
	<div dojoType="dijit.Declaration" widgetClass="album.Upload">
			<div dojoType="dijit.TitlePane" region="center" dojoAttachPoint="container" title="Upload Photo">
				<table width="100%" border="0" cellspacing="0" cellpadding="0">
	 				<tr>
						<td class="leftCol">
							<div>
								Select Album:
								<select  id="selectalbum" autoComplete="true" onfocus="populateSelect" dojoType="dijit.form.FilteringSelect">

								</select>
								
							</div>
							
							<span id="fTypes">Choose from these types:</span>
							<div id="btn0" class="browse" dojoType="dijit.form.Button" onfocus="activateUploader();">Select Images...</div>
							
							<textarea cols="50" rows="6" id="fileToUpload"></textarea>
							<div id="uploadBtn" class="uploadBtn" onClick="doUpload();" dojoType="dijit.form.Button">Upload</div>
						</td>
	 				</tr>
				</table>
			</div>
	</div>
	
        <div class dojoType="dijit.layout.BorderContainer" gutters="false" id="borderContainerTwo" jsId="borderContainerTwo">
            <div class="top" dojoType="dijit.layout.ContentPane"  region="top" splitter="false">
            	<h1>Apache PhotArk Gallery Admin <a href="/photark/"  target="_blank"> <em id="visit-gallery">Visit Gallery</em></a></h1>
            </div>
            <div dojoType="dijit.layout.BorderContainer" liveSplitters="false" design="sidebar" region="center" jsId="mainSplit" id="mainSplit">
                <div dojoType="dijit.layout.AccordionContainer" minSize="20" style="width: 300px;" id="leftAccordion" region="leading" splitter="true">
                    <div dojoType="dijit.layout.AccordionPane" title="Albums">
						<div dojoType="dijit.Tree" model="folderModel" openOnClick="true" showRoot="false" >
							<script type="dojo/method" event="onClick" args="item">
								console.log(item);	
								if(item.name == "Upload Photo"){
									var up = dijit.byId('uploadPhoto');
									if(up == null){
										up = new album.Upload({id: "uploadPhoto"}).container;
									}
									if(up.container == null){
										tabs.removeChild(newAlbum);
										tabs.addChild(up);
										tabs.selectChild(up);
									}
									else{
										var wid = dijit.byNode(up.container.domNode);
										tabs.removeChild(newAlbum);
										tabs.addChild(wid);
										tabs.selectChild(wid);
									}
								}
								else{
									var up = dijit.byId('uploadPhoto');
									var wid = dijit.byNode(up.container.domNode);
									tabs.removeChild(wid);
								   	tabs.addChild(newAlbum);
								   	tabs.selectChild(newAlbum);
								}
								
							</script>
						</div>
                    </div>
                    <div dojoType="dijit.layout.AccordionPane" title="Settings" selected="true">
                    </div>
                </div>
                <!-- end AccordionContainer -->
				
				
				  <div class dojoType="dijit.layout.TabContainer"  id="tabs" jsId="tabs" region="center" gutters="false">
				  	<div dojoType="dijit.TitlePane" title="Create New Album" region="center" id="newAlbum" jsId="newAlbum">
				  		<div id="albumCreated" jsId="albumCreated"> </div>
						<form dojoType="dijit.form.Form" id ="newAlbumForm" jsId="newAlbumForm">
							<table>
								<tr>
									<td><label for="albumName">Album Name:</label></td>
									<td><input dojoType="dijit.form.TextBox" id="albumName" name="label"></td>
								</tr>
								<tr>
									<td colspan=2 align=center><button dojoType="dijit.form.Button" onClick="createAlbum">Create</button></td>
								</tr>
							</table>
						</form>
					</div>	  
				</div>
				  
				
            </div>
        </div>
	
    </body>
</html>