<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- Copyright (c) 2012 Rally Software Development Corp. All rights reserved -->
<html>
<head>
  <title>DefectSummaryMatrix</title>
  <meta name="Name" content="App: DefectSummaryMatrix" />
  <meta name="Version" content="2012.11.21" />
  <meta name="Vendor" content="Rally Software" />

  <script type ="text/javascript" src="/apps/1.32/sdk.js"></script>
  <script type ="text/javascript">
    function DefectSummaryMatrix() {
    	var defectData;
    	var table;
    	var total = "Total";
    	var rallyDataSource = new rally.sdk.data.RallyDataSource('__WORKSPACE_OID__', 
    															'__PROJECT_OID__', 
    															'__PROJECT_SCOPING_UP__', 
    															'__PROJECT_SCOPING_DOWN__');
    	var header = rally.sdk.ui.AppHeader;
    	header.showPageTools(true);
    	header.removePageTool("print");
    	header.addPageTool({
    		key:"Previous Version",
    		label:"Previous Version",
    		onClick:  function() {
    			if (parent && parent.window && parent.window.location) {
    				parent.window.location = "http://agilecommons.org/posts/4d4d00c953";
    			}
    			else {
    				window.location = "http://agilecommons.org/posts/4d4d00c953";
    			}
    		}
    	});
    
    	function initialize3DArray(rows, cols) {
            defectData = [cols];
            for (var c = 0; c <= cols; c++) {
                defectData[c] = [];
                for (var r = 0; r <= rows; r++) {
                    defectData[c][r] = [];
                }
            }
        }
    
        function addDefect(column, row, defect) {
            defectData[column][row].push(defect);
        }
    
        function setOwner(defect) {
            if (defect.Owner !== null) {
                if (defect.Owner.DisplayName !== "") {
                    defect.Owner = defect.Owner.DisplayName;
                } else {
                    defect.Owner = defect.Owner.LoginName;
                }
            } else {
                defect.Owner = "";
            }
        }
    
        function findIndex(value, listOfValues) {
            for (var i = 0; i < listOfValues.length; i++) {
                if (listOfValues[i] == value) {
                    return i;
                }
            }
            return 0;
            /* Returning 0 to accommodate having null values in the priority field even though the object has "None" in WSAPI */
        }
    
    	// return 3D array by priority, state and list of defects
        function countByPriorityAndState(defectResults) {
            var maxRow = defectResults.defectPriorities.length;
            var maxCol = defectResults.defectStates.length;
    
            initialize3DArray(maxRow, maxCol);
    
            // cycle through defects and increment the appropriate state/priority combo in the array
            var row, column;
    
            for (var i = 0; i < defectResults.defects.length; i++) {
                column = findIndex(defectResults.defects[i].State, defectResults.defectStates);
                row = findIndex(defectResults.defects[i].Priority, defectResults.defectPriorities);
                var defect = defectResults.defects[i];
                addDefect(column, row, defect);
                addDefect(column, maxRow, defect);
                addDefect(maxCol, row, defect);
                addDefect(maxCol, maxRow, defect);
                setOwner(defect);
            }
        }
    
        var defectQuery = function() {
            var selected = releaseDropdown.getSelectedName();
            var releaseQuery = '(Release.Name = "' + selected + '")';
            var queryObject = [];
            queryObject[0] = { key: 'defectStates', type: 'Defect', attribute: 'State' };
            queryObject[1] = { key: 'defectPriorities', type: 'Defect', attribute: 'Priority' };
            queryObject[2] = {
                key: 'defects',
                type: 'Defect',
                query: releaseQuery,
                fetch: 'FormattedID,Name,State,Priority,ScheduleState,ObjectID,Description,owner,DisplayName,LoginName'
            };
            rallyDataSource.findAll(queryObject, populateTable);
        };
    
        var destroyDefectList = function() {
            if (defectList) {
                defectList.destroy();
                defectList = null;
                var displayHeader = dojo.byId('displayHeader');
    
                if(displayHeader) {
                    displayHeader.innerHTML = '';
                }
            }
        };
    
        var populateTable = function (results) {
            var tableDiv = document.getElementById('defects');
            var states = [];
            states[0] = "&nbsp";
            for (var i = 0; i < results.defectStates.length; i++) {
                states[i + 1] = results.defectStates[i];
            }
            states[results.defectStates.length + 1] = total;
    
            var config = { 'columnKeys': states, 'sortingEnabled' : false };
    
            if (table) {
                table.destroy();
            }
            table = new rally.sdk.ui.Table(config);
    
            var priorities = [];
            for (var j = 0; j < results.defectPriorities.length; j++) {
                priorities[j] = results.defectPriorities[j];
                table.setCell(j, 0, priorities[j]);
            }
            table.setCell(results.defectPriorities.length, 0, total);
    
            countByPriorityAndState(results);
    
            var onTableClick = function(obj, args) {
                var col = args.columnIndex - 1;
                if (col < 0) {
                    return;
                }
                var row = args.rowIndex;
                var displayHeaderDiv = dojo.byId('displayHeader');
                var columnText = args.columnHeader + " ";
                var rowText = obj.getCell(row, 0) + " ";
                var preface = "";
                var postface = "";
                if (columnText === total + " ") {
                    columnText = "";
                    preface = "All ";
                }
                if (rowText === " ") {
                    rowText = "";
                    postface = " Without a Priority";
                }
                if (rowText === total + " ") {
                    // rowText = "";
                    preface = "All ";
                }
    
                destroyDefectList();
    
                displayHeaderDiv.innerHTML = preface + columnText + rowText + "Defects " + postface;
    
                var displayDiv = dojo.byId('display');
                var defectConfig = {
                    'columnKeys': ['FormattedID','Name','State','Priority', 'Owner']
                };
    
                defectList = new rally.sdk.ui.Table(defectConfig);
                defectList.addRows(defectData[col][row]);
                for (var i = 0; i < defectData[col][row].length; i++) {
                    var target = rally.sdk.util.Ref.createRallyDetailUrl(defectData[col][row][i]._ref);
                    defectList.setCell(i, 0, "<a href=" + target + " target=_blank>" + defectData[col][row][i].FormattedID + "</a>");
                }
    
                defectList.display(displayDiv);
            };
    
            table.addEventListener("onCellClick", onTableClick);
            // make formattedID link to work products
            for (var col = 0; col < defectData.length; col++) {
                for (var row = 0; row < defectData[col].length; row++) {
                    table.setCell(row, col + 1, "<a href='#' onclick='return false;'>" + defectData[col][row].length + "</a>");
                }
            }
            table.display(tableDiv);
        };
    
        var releaseDiv = dojo.byId('release');
        var releaseDropdown = new rally.sdk.ui.ReleaseDropdown({}, rallyDataSource);
        var defectList = null;
        var releaseDropdownWrapper = function(obj, args) {
            destroyDefectList();
            defectQuery(obj, args);
        };
        releaseDropdown.display(releaseDiv, releaseDropdownWrapper);
    }

  </script>

  <style type="text/css">
        #release {
    	margin-bottom: 15px;
    }
    
    #displayHeader {
    	font-weight: bold;
    	width: 100%;
    	text-align: center;
    }
  </style>

  <script type="text/javascript">
    function onLoad() {
      var appCustom = new DefectSummaryMatrix();
    }

    rally.addOnLoad(onLoad);
  </script>
</head>

<body>
  <div id="release"></div>
  <div id="defects"></div>
  <br/>
  <br/>

  <div id="displayHeader"></div>
  <div id="display"></div>
</body>
</html>