type DrawBarOptionsDraw_Dev = DrawBarOptionsDraw & {
	circle?: any,
}


type DrawBarOptionsEdit_Dev = DrawBarOptionsEdit & {
	featureGroup: L.FeatureGroup
};


init() {
		const { drawBar } = this.context.props;

		if (drawBar && drawBar.enable) {
			this.createElement(drawBar);

			// Add layer-line to layer manager
			this.context.layersController.addingDrawableLayerToLayerController(this.drawableLayer);

			if (this.element && this.drawableLayer) {
				this.context.map.on(L.Draw.Event.CREATED, this.onDrawCreated); // on-click handler
				this.context.map.on(L.Draw.Event.EDITED, this.onDrawEdited);
				this.context.map.on(L.Draw.Event.DELETED, this.onDrawDeleted);
				// Add plugin controls to Toolbar
				this.context.onAddControlToFeatures(FeaturesNames.DRAWBAR_COMP, this);
				this.context.map.on('overlayremove', this.onOverlayRemoved);
                this.context.map.on('overlayadd', this.onOverlayAdded);
			}

			if (this.context.props.layersController.enable) {
				// Add drawbar to layer controller
				this.context.layersController.element.addOverlay( this.drawableLayer, "Shapes", {groupName : "Draw Bar"} );
			}
		}
	}


public getDrawLayer(): L.FeatureGroup {
		return this.drawableLayer;
	}


public export(): WktShape[] {
		const exportDrawableLayers: Array<WktShape> = [];
		const layers = this.drawableLayer.getLayers();

		layers.forEach((layer: L.Layer) => {
			const manager: ShapeManagerInterface | null = ShapeManagerRepository.getManagerByShapeDefLayer(layer);
			if (manager) {
				const shape: ShapeObject = <ShapeObject>manager.getShapeObjectFromDrawingLayer(layer);
				const wkt: string   = manager.shapeObjectToWkt(shape);
				const id: number = L.Util.stamp(layer);	// Get leaflet layer id
				const areaSize: number = manager.getAreaSize(shape);
				exportDrawableLayers.push({ wkt, id, areaSize });
			}
		});
		return exportDrawableLayers;
	}


public clear() {
		this.drawableLayer.clearLayers();
	}


public getMultiPolygon() {
		const layers = this.drawableLayer.getLayers();
		const polygonList: PolygonShape[] = [];

		layers.forEach((layer: L.Layer) => {
			const manager: ShapeManagerInterface | null = ShapeManagerRepository.getManagerByShapeDefLayer(layer);

			if (manager && manager.getType() === ShapeType.POLYGON) {
				const shape: PolygonShape = <any>manager.getShapeObjectFromDrawingLayer(layer);
				polygonList.push(shape);
			}
		});

		const multiPolygon: MultiPolygonShape = {
			polygons: polygonList
		};

		const shapeObj: ShapeObject = {
			type: ShapeType.MULTIPOLYGON,
			shape: multiPolygon
		};

		const manager: ShapeManagerInterface | null = ShapeManagerRepository.getManagerByType(ShapeType.MULTIPOLYGON);

		if (manager) {
			const wkt = manager.shapeObjectToWkt(shapeObj);

			return wkt;
		} else {
			console.error('Undetected manager');
			return null;
		}
	}


// TBD
public toggleUnits(): void {
		console.log('TOOL BAR: toggleUnits() is TBD');
	}


public onOverlayRemoved(e: any): void {
		// todo: change hardcoded "Draw Bar" to variable
		if (e.group.name === "Draw Bar") {
			// parent element of all drawing section has the class of "leaflet-draw-toolbar-top"
            const drawSectionParent = <HTMLElement>document.getElementById("draw-shapes-section");
			if (drawSectionParent) {
				const sectionsToDisable = <HTMLElement[]>Array.from([drawSectionParent, drawSectionParent.firstElementChild]);
				Utils.addClassesToHtmlCollection(sectionsToDisable, "disabled-toolbar-section");
				const actionElementsToDisable = <HTMLElement[]>Array.from(drawSectionParent.firstElementChild.children);
				Utils.addClassesToHtmlCollection(actionElementsToDisable, "disabled-toolbar-action", "leaflet-disabled");
			}
		}
    }


public onOverlayAdded(e: any): void {
        // todo: change hardcoded "Draw Bar" to variable
        if (e.group.name === "Draw Bar") {
            // parent element of all drawing section has the class of "leaflet-draw-toolbar-top"
            const drawSectionParent = <HTMLElement>document.getElementById("draw-shapes-section");
            if (drawSectionParent) {
                const elementsToEnable = <HTMLElement[]>Array.from([drawSectionParent, drawSectionParent.firstElementChild]);
                Utils.removeClassesFromHtmlCollection(elementsToEnable, "disabled-toolbar-section");
                const actionElementsToEnable = <HTMLElement[]>Array.from(drawSectionParent.firstElementChild.children);
                Utils.removeClassesFromHtmlCollection(actionElementsToEnable, "disabled-toolbar-action", "leaflet-disabled");
            }
        }
    }


public import(wktShapesArr: Array<WktShape>) {
		// Iterate all imported WktShapes
		wktShapesArr.forEach((item: WktShape) => {
			const shapeDef: ShapeDefinition = {
				shapeWkt: item.wkt,
				data: {
					name: 'Editable layer', // TBD get isSelected from extended data
					isSelected: false		// TBD get isSelected from extended data
				}
			};
			const manager: ShapeManagerInterface | null = ShapeManagerRepository.getManagerByWkt(item.wkt);

			if (manager) {
				// Add shapeObject from wkt
				if (!shapeDef.shapeObject && shapeDef.shapeWkt) {
					shapeDef.shapeObject = manager.shapeWktToObject(shapeDef.shapeWkt);
				}
				const leafletObject: L.Layer | L.FeatureGroup = manager.addShapeToLayer(shapeDef, this.drawableLayer, {
					click: Utils.shapeOnClickHandler.bind(this, manager, this.context)
				});
				Utils.createBubble(leafletObject, BUBBLE_TYPE.TOOLTIP);
				leafletObject.layerName = LayerNames.DRAWABLE_LAYER;
			}
		});

		// Run onEndImportDraw Callback
		const allDrawableLayers: WktShape[] = this.export();
		const gisViewerEl: HTMLGisViewerElement = document.querySelector('gis-viewer');
		gisViewerEl.emitEndImportDraw(allDrawableLayers);
	}


// Draw listener
private drawEventHandler(drawEvent: any) {
		const manager: ShapeManagerInterface = ShapeManagerRepository.getManagerByShapeDefLayer(drawEvent.layer);

		let layerEnumType: ShapeType = ShapeManagerRepository.getTypeNumberByDrawableTypeName(drawEvent.layerType);
		if (layerEnumType === ShapeType.MARKER) {
			const className: string = _.get<any, string | undefined>(drawEvent.layer, 'options.icon.options.className');

			if (className === textIconClassName) {
				// Label support
				layerEnumType = ShapeType.LABEL;
				editTextMarker(drawEvent.layer);

				drawEvent.layer.on("dblclick", () => {
					editTextMarker(drawEvent.layer);
				});
			}
		}
		// Add this draw to draw-layer
		const leafletObject: L.Layer | L.FeatureGroup = manager.addShapeToLayer(drawEvent.layer.shapeDef, this.drawableLayer, {
			click: Utils.shapeOnClickHandler.bind(this, manager, this.context)
		});
		Utils.createBubble(leafletObject, BUBBLE_TYPE.TOOLTIP);
	}


private createElement(options?: DrawBarOptions): void {
		// Create edit layer
		if (!this.drawableLayer) {
			this.drawableLayer = new L.FeatureGroup([]);
		}

		const optionsDev: DrawBarOptions_Dev = <DrawBarOptions_Dev>options;
		const isCircle: boolean = _.get(optionsDev, 'draw.circle');

		// Component initialization
		if (isCircle) {
			const { mapUnits } = this.context;
			optionsDev.draw.circle = {
				metric: mapUnits === Units.METRIC ? true : false
			};
		}

		const removeVal: boolean = _.get(optionsDev, 'edit.remove') ? true : false;

		const drawBarOptionsEditDev: DrawBarOptionsEdit_Dev = {
			featureGroup: this.drawableLayer,
			remove: removeVal
		};

		const drawBarOptionsDev: DrawBarOptions_Dev = {
			draw: optionsDev && optionsDev.draw ? optionsDev.draw : {},
			edit: drawBarOptionsEditDev
		};
		// Create draw controls
		this.element = new L.Control.Draw(drawBarOptionsDev);
		this.context.map.addControl(this.element); // add this control to map
	}


private createShapeDefFromDrawLayer(layer: L.Layer, shapeType: ShapeType): ShapeDefinition {
		const manager: ShapeManagerInterface = ShapeManagerRepository.getManagerByType(shapeType);
		if (!manager) { return null; }

		// Calculate area size
		const shapeObject: ShapeObject = manager.getShapeObjectFromDrawingLayer(layer);

		// Create WktShape from wkt, id, area size
		const shapeWkt: string = manager.shapeObjectToWkt(shapeObject);
		const shapeData: ShapeData = { name: 'Editable layer', isSelected: false, count: 1 };
		return { shapeObject, shapeWkt, data: shapeData };
	}


private getWktShapeFromWkt(drawShapeLayer: any): WktShape {
		const manager: ShapeManagerInterface = ShapeManagerRepository.getManagerByShapeDefLayer(drawShapeLayer);

		if (manager) {
			// Create WktShape from wkt, id, area size
			const { shapeWkt, shapeObject } = drawShapeLayer.shapeDef;
			const id: number = L.Util.stamp(drawShapeLayer);	// Get leaflet layer id
			const areaSize: number = this.calculateAreaSizeFromShapeObj(manager, shapeObject);
			return { wkt: shapeWkt, areaSize, id };
		} else {
			console.error('Cant find shape manager by ShapeManagerRepository.getManagerByShapeDefLayer()', drawShapeLayer);
			return null;
		}
	}


private onDrawCreated(e: any): void {
		const layerEnumType: ShapeType = ShapeManagerRepository.getTypeNumberByDrawableTypeName(e.layerType);
		const shapeDef: ShapeDefinition = this.createShapeDefFromDrawLayer(e.layer, layerEnumType);

		// Add shapeDef to layer
		e.layer = this.addShapeDefToLayer(e.layer, shapeDef) as L.FeatureGroup;

		// Event handler
		this.drawEventHandler(e);

		// Use callback of onDrawCreated
		const wktShape: WktShape = this.getWktShapeFromWkt(e.layer);
		const gisViewerEl: HTMLGisViewerElement = document.querySelector('gis-viewer');
		gisViewerEl.emitDrawCreated(wktShape);
	}


private onDrawEdited(e: any): void {
		// Save output
		const wktList: WktShape[] = [];

		e.layers.eachLayer((layer: L.Layer) => {
			// Create shapeDef object for this layer
			const { shapeObject, shapeWkt } = this.createShapeDefFromDrawLayer(layer, layer.shapeDef.shapeObject.type);
			// Update just shapeObject, and shapeWkt
			_.merge(layer.shapeDef, { shapeObject, shapeWkt });

			// Create WktShape from layer
			const wktShape: WktShape = this.getWktShapeFromWkt(layer);
			if (wktShape) {
				wktList.push(wktShape);
			}
		});
		// Use callback of onDrawEdited
		const gisViewerEl: HTMLGisViewerElement = document.querySelector('gis-viewer');
		gisViewerEl.emitDrawEdited(wktList);
	}


private onDrawDeleted(e: any): void {
		const wktList: WktShape[] = this.getWktShapeListFromEvent(e);
		// Use callback of onDrawDeleted
		const gisViewerEl: HTMLGisViewerElement = document.querySelector('gis-viewer');
		gisViewerEl.emitDrawDeleted(wktList);
	}


private getWktShapeListFromEvent(e: any) {
		const wktList: WktShape[] = [];
		e.layers.eachLayer((layer: L.Layer) => {
			const wkt: WktShape = this.createWktFromEditableLayer(layer);
			if (wkt) {
				wktList.push(wkt);
			}
		});
		return wktList;
	}


private calculateAreaSizeFromShapeObj(manager: ShapeManagerInterface, shapeObj: ShapeObject): number {
		const areaSize = manager.getAreaSize(shapeObj);
		return areaSize || 0;
	}


private createWktFromEditableLayer(drawShapeLayer: L.Layer): WktShape {
		const manager: ShapeManagerInterface = ShapeManagerRepository.getManagerByShapeDefLayer(drawShapeLayer);

		if (manager) {
			// Calculate area size
			const shapeObj: ShapeObject = manager.getShapeObjectFromDrawingLayer(drawShapeLayer);

			// Create WktShape from wkt, id, area size
			const wkt: string = manager.shapeObjectToWkt(shapeObj);
			const id: number = L.Util.stamp(drawShapeLayer);	// Get leaflet layer id
			const areaSize: number = this.calculateAreaSizeFromShapeObj(manager, shapeObj);
			return { wkt, areaSize, id };
		} else {
			console.error('Cant find shape manager by ShapeManagerRepository.getManagerByShapeDefLayer()', drawShapeLayer);
			return null;
		}
	}


private addShapeDefToLayer(layer: L.FeatureGroup, shapeDef: ShapeDefinition): L.FeatureGroup {
		_.merge(layer, { shapeDef, layerName: LayerNames.DRAWABLE_LAYER });
		return layer;
	}


export class NullFullScreenAd extends NullAd implements IFullScreenAd {
    public async show(): Promise<AdResult> {
        return AdResult.Failed;
    }
}


public async show(): Promise<AdResult> {
        return AdResult.Failed;
    }


(node,quantity) => {
    // 処理分岐
    if(node.調達方法 === "作成")     return buildCreateNode(node,quantity);
    if(node.調達方法 === "共通素材") return buildCommonNode(node,quantity);
    if(node.調達方法 === "NPC")      return buildNpcNode(node,quantity);
    if(node.調達方法 === "自力調達") return buildUserNode(node,quantity);
    return buildUnknownNode(node,quantity);
}


type tBuildNode = (node:Readonly<tTreeNodeD>, quantity:number) => tTreeNode


@NgModule({
	imports: [
		CommonModule,
		SharedModule,
		IonicModule,
		PageInfoTitleModule
	],

	declarations: [AccountVerificationComponent],
	exports: [AccountVerificationComponent],
	entryComponents: [AccountVerificationComponent]
})
export class AccountVerificationModule { }


export function insert(data: unknown): SqlFragment {
  if (typeof data !== 'object' || data === null) {
    throw new Error('Data must be an object');
  }

  if (Array.isArray(data)) {
    throw new Error('Array is not supported');
  }

  const keys = Object.keys(data);
  const length = keys.length;
  const sqlFragments = new Array(length);
  const values = new Array(length - 1);
  const sb = [];

  sb.push('(');
  let i = 0;
  while (i < length) {
    const column = keys[i];
    // tslint:disable-next-line:no-any
    values[i] = (data as any)[column];
    i++;
    sb.push(escapeIdentifier(column), ',');
    sqlFragments[i] = ',';
  }
  sb[sb.length - 1] = ') VALUES (';
  sqlFragments[0] = sb.join('');
  sqlFragments[i] = ')';

  return new SqlFragment(sqlFragments, values);
}


export class CS310View extends StudentView {

    private teams: TeamTransport[];

    constructor(remoteUrl: string) {
        super();
        Log.info("CS310View::<init>");
        this.remote = remoteUrl;
    }

    public renderPage(opts: {}) {
        Log.info('CS310View::renderPage() - start; options: ' + opts);
        const that = this;
        const start = Date.now();

        UI.showModal("Fetching data.");
        super.render().then(function() {
            // super render complete; do custom work
            return that.renderStudentPage();
        }).then(function() {
            Log.info('CS310View::renderPage(..) - prep & render took: ' + UI.took(start));
            UI.hideModal();
        }).catch(function(err) {
            Log.error('CS310View::renderPage() - ERROR: ' + err);
            UI.hideModal();
        });
    }

    private async renderStudentPage(): Promise<void> {
        UI.showModal('Fetching Data');
        try {
            // grades done in StudentView
            // repos done in StudentView

            // teams
            const teams = await this.fetchTeamData();
            this.teams = teams;
            await this.renderTeams(teams);

            Log.info('CS310View::renderStudentPage(..) - done');
        } catch (err) {
            Log.error('Error encountered: ' + err.message);
        }
        UI.hideModal();
        return;
    }

    // private async fetchData(endpoint: string): Promise<any> {
    //     const url = this.remote + endpoint;
    //     const response = await fetch(url, super.getOptions());
    //     if (response.status === 200) {
    //         Log.trace('CS310View::fetchData( ' + endpoint + ' ) - 200 received');
    //         const json = await response.json();
    //         Log.trace('CS310View::fetchData( ' + endpoint + ' ) - payload: ' + JSON.stringify(json));
    //         if (typeof json.success !== 'undefined') {
    //             Log.trace('CS310View::fetchData( ' + endpoint + ' ) - success: ' + json.success);
    //             return json.success;
    //         } else {
    //             Log.trace('CS310View::fetchData( ' + endpoint + ' ) - ERROR: ' + json.failure.message);
    //             throw new Error(json.failure.message);
    //             // UI.showError(json.failure);
    //         }
    //     } else {
    //         Log.trace('CS310View::fetchData( ' + endpoint + ' ) - teams !200 received');
    //     }
    //
    //     UI.hideModal();
    //     return [];
    // }

    private async fetchTeamData(): Promise<TeamTransport[]> {

        // this.teams = null;

        // const url = this.remote + '/portal/teams';
        // const response = await fetch(url, super.getOptions());
        // if (response.status === 200) {
        //     Log.trace('CS310View::fetchTeamData(..) - teams 200 received');
        //     const json = await response.json();
        //     Log.trace('CS310View::fetchTeamData(..) - teams payload: ' + JSON.stringify(json));
        //     if (typeof json.success !== 'undefined') {
        //         Log.trace('CS310View::fetchTeamData(..) - teams success: ' + json.success);
        //         return json.success as TeamTransport[];
        //     } else {
        //         Log.trace('CS310View::fetchTeamData(..) - teams ERROR: ' + json.failure.message);
        //         UI.showError(json.failure);
        //     }
        // } else {
        //     Log.trace('CS310View::fetchTeamData(..) - teams !200 received');
        // }
        try {
            this.teams = null;
            let data: TeamTransport[] = await this.fetchData('/portal/teams');
            if (data === null) {
                data = [];
            }
            this.teams = data;
            return data;
        } catch (err) {
            Log.error('CS310View::fetchTeamData(..)' + err.message);
            this.teams = [];
            return [];
        }

    }

    private async renderTeams(teams: TeamTransport[]): Promise<void> {
        Log.trace('CS310View::renderTeams(..) - start');
        const that = this;

        // make sure these are hidden
        UI.hideSection('studentSelectPartnerDiv');
        UI.hideSection('studentPartnerDiv');

        // skip this all for now; we will redeploy when teams can be formed
        // if (Date.now() > 0) {
        //     return;
        // }

        let projectTeam = null;
        for (const team of teams) {
            if (team.delivId === "project") {
                projectTeam = team;
            }
        }

        if (projectTeam === null) {
            // no team yet

            const button = document.querySelector('#studentSelectPartnerButton') as OnsButtonElement;
            button.onclick = function(evt: any) {
                Log.info('CS310View::renderTeams(..)::createTeam::onClick');
                that.formTeam().then(function(team) {
                    Log.info('CS310View::renderTeams(..)::createTeam::onClick::then - team created');
                    that.teams.push(team);
                    if (team !== null) {
                        that.renderPage({}); // simulating refresh
                    }
                }).catch(function(err) {
                    Log.info('CS310View::renderTeams(..)::createTeam::onClick::catch - ERROR: ' + err);
                });
            };

            UI.showSection('studentSelectPartnerDiv');
        } else {
            // already on team
            UI.showSection('studentPartnerDiv');

            const tName = document.getElementById('studentPartnerTeamName');
            // const pName = document.getElementById('studentPartnerTeammates');
            const team = projectTeam;

            // if (team.URL !== null) {
            //     tName.innerHTML = '' + team.id + '';
            // } else {
            tName.innerHTML = team.id;
            // }
            // pName.innerHTML = team.people[0]; // JSON.stringify(team.people);
        }
    }

    private async formTeam(): Promise<TeamTransport> {
        Log.info("CS310View::formTeam() - start");
        const otherId = UI.getTextFieldValue('studentSelectPartnerText');
        const myGithubId = this.getStudent().githubId;
        const payload: TeamFormationTransport = {
            delivId:   'project', // only one team in cs310 (and it is always called project)
            githubIds: [myGithubId, otherId]
        };
        const url = this.remote + '/portal/team';
        const options: any = this.getOptions();
        options.method = 'post';
        options.body = JSON.stringify(payload);

        Log.info("CS310View::formTeam() - URL: " + url + "; payload: " + JSON.stringify(payload));
        const response = await fetch(url, options);

        Log.info("CS310View::formTeam() - responded");

        const body = await response.json() as Payload;

        Log.info("CS310View::formTeam() - response: " + JSON.stringify(body));

        if (typeof body.success !== 'undefined') {
            // worked
            return body.success as TeamTransport;
        } else if (typeof body.failure !== 'undefined') {
            // failed
            UI.showError(body);
            return null;
        } else {
            Log.error("CS310View::formTeam() - else ERROR: " + JSON.stringify(body));
        }
    }

}


public renderPage(opts: {}) {
        Log.info('CS310View::renderPage() - start; options: ' + opts);
        const that = this;
        const start = Date.now();

        UI.showModal("Fetching data.");
        super.render().then(function() {
            // super render complete; do custom work
            return that.renderStudentPage();
        }).then(function() {
            Log.info('CS310View::renderPage(..) - prep & render took: ' + UI.took(start));
            UI.hideModal();
        }).catch(function(err) {
            Log.error('CS310View::renderPage() - ERROR: ' + err);
            UI.hideModal();
        });
    }


private async renderStudentPage(): Promise<void> {
        UI.showModal('Fetching Data');
        try {
            // grades done in StudentView
            // repos done in StudentView

            // teams
            const teams = await this.fetchTeamData();
            this.teams = teams;
            await this.renderTeams(teams);

            Log.info('CS310View::renderStudentPage(..) - done');
        } catch (err) {
            Log.error('Error encountered: ' + err.message);
        }
        UI.hideModal();
        return;
    }


// private async fetchData(endpoint: string): Promise<any> {
//     const url = this.remote + endpoint;
//     const response = await fetch(url, super.getOptions());
//     if (response.status === 200) {
//         Log.trace('CS310View::fetchData( ' + endpoint + ' ) - 200 received');
//         const json = await response.json();
//         Log.trace('CS310View::fetchData( ' + endpoint + ' ) - payload: ' + JSON.stringify(json));
//         if (typeof json.success !== 'undefined') {
//             Log.trace('CS310View::fetchData( ' + endpoint + ' ) - success: ' + json.success);
//             return json.success;
//         } else {
//             Log.trace('CS310View::fetchData( ' + endpoint + ' ) - ERROR: ' + json.failure.message);
//             throw new Error(json.failure.message);
//             // UI.showError(json.failure);
//         }
//     } else {
//         Log.trace('CS310View::fetchData( ' + endpoint + ' ) - teams !200 received');
//     }
//
//     UI.hideModal();
//     return [];
// }
private async fetchTeamData(): Promise<TeamTransport[]> {

        // this.teams = null;

        // const url = this.remote + '/portal/teams';
        // const response = await fetch(url, super.getOptions());
        // if (response.status === 200) {
        //     Log.trace('CS310View::fetchTeamData(..) - teams 200 received');
        //     const json = await response.json();
        //     Log.trace('CS310View::fetchTeamData(..) - teams payload: ' + JSON.stringify(json));
        //     if (typeof json.success !== 'undefined') {
        //         Log.trace('CS310View::fetchTeamData(..) - teams success: ' + json.success);
        //         return json.success as TeamTransport[];
        //     } else {
        //         Log.trace('CS310View::fetchTeamData(..) - teams ERROR: ' + json.failure.message);
        //         UI.showError(json.failure);
        //     }
        // } else {
        //     Log.trace('CS310View::fetchTeamData(..) - teams !200 received');
        // }
        try {
            this.teams = null;
            let data: TeamTransport[] = await this.fetchData('/portal/teams');
            if (data === null) {
                data = [];
            }
            this.teams = data;
            return data;
        } catch (err) {
            Log.error('CS310View::fetchTeamData(..)' + err.message);
            this.teams = [];
            return [];
        }

    }


private async renderTeams(teams: TeamTransport[]): Promise<void> {
        Log.trace('CS310View::renderTeams(..) - start');
        const that = this;

        // make sure these are hidden
        UI.hideSection('studentSelectPartnerDiv');
        UI.hideSection('studentPartnerDiv');

        // skip this all for now; we will redeploy when teams can be formed
        // if (Date.now() > 0) {
        //     return;
        // }

        let projectTeam = null;
        for (const team of teams) {
            if (team.delivId === "project") {
                projectTeam = team;
            }
        }

        if (projectTeam === null) {
            // no team yet

            const button = document.querySelector('#studentSelectPartnerButton') as OnsButtonElement;
            button.onclick = function(evt: any) {
                Log.info('CS310View::renderTeams(..)::createTeam::onClick');
                that.formTeam().then(function(team) {
                    Log.info('CS310View::renderTeams(..)::createTeam::onClick::then - team created');
                    that.teams.push(team);
                    if (team !== null) {
                        that.renderPage({}); // simulating refresh
                    }
                }).catch(function(err) {
                    Log.info('CS310View::renderTeams(..)::createTeam::onClick::catch - ERROR: ' + err);
                });
            };

            UI.showSection('studentSelectPartnerDiv');
        } else {
            // already on team
            UI.showSection('studentPartnerDiv');

            const tName = document.getElementById('studentPartnerTeamName');
            // const pName = document.getElementById('studentPartnerTeammates');
            const team = projectTeam;

            // if (team.URL !== null) {
            //     tName.innerHTML = '' + team.id + '';
            // } else {
            tName.innerHTML = team.id;
            // }
            // pName.innerHTML = team.people[0]; // JSON.stringify(team.people);
        }
    }


private async formTeam(): Promise<TeamTransport> {
        Log.info("CS310View::formTeam() - start");
        const otherId = UI.getTextFieldValue('studentSelectPartnerText');
        const myGithubId = this.getStudent().githubId;
        const payload: TeamFormationTransport = {
            delivId:   'project', // only one team in cs310 (and it is always called project)
            githubIds: [myGithubId, otherId]
        };
        const url = this.remote + '/portal/team';
        const options: any = this.getOptions();
        options.method = 'post';
        options.body = JSON.stringify(payload);

        Log.info("CS310View::formTeam() - URL: " + url + "; payload: " + JSON.stringify(payload));
        const response = await fetch(url, options);

        Log.info("CS310View::formTeam() - responded");

        const body = await response.json() as Payload;

        Log.info("CS310View::formTeam() - response: " + JSON.stringify(body));

        if (typeof body.success !== 'undefined') {
            // worked
            return body.success as TeamTransport;
        } else if (typeof body.failure !== 'undefined') {
            // failed
            UI.showError(body);
            return null;
        } else {
            Log.error("CS310View::formTeam() - else ERROR: " + JSON.stringify(body));
        }
    }


export function Celsius(config: CelsiusConfigurationInstance): Promise<CelsiusInstance>;


/**
     * Class which encapsulates errors raised within Celsius SDK.
     *
     * If the error has occurred internally within the Celsius SDK, status and slug properties will be null.
     */
export class CelsiusSDKError extends Error {
        /** Number representing HTTP status code returned by the Wallet API. Will be null if the error didn't occur on Wallet API. **/
        status: number | null
        /** Message containing a more detailed description of the error which occurred. **/
        message: string
        /** Value returned by Wallet API that is used to distinguish between different errors. Will be null if the error didn't occur on Wallet API. **/
        slug: string
        /** Original error that was thrown and used to construct CelsiusSDKError. Will be null in case an instance of CelsiusSDKError is explicitly being thrown. **/
        originalError: Error | null
    }


/**
     * Class which encapsulates validation errors before the request gets processed further.
     */
export class ValidationError {
        /** Number representing HTTP status code returned by the Wallet API. **/
        status: number
        /** Array of ClassValidatorError objects. See https://www.npmjs.com/package/class-validator#validation-errors for more details. **/
        message: ClassValidatorError[]
    }


interface CelsiusConfigurations {
        staging: Partial<CelsiusConfigurationInstance>;
        production: Partial<CelsiusConfigurationInstance>;
    }


interface CelsiusConfigurationInstance {
        /** Base URL of the Celsius API */
        baseUrl?: string;
        /** Public key required for preventing man-in-the-middle attacks */
        publicKey?: string;
        /** The partner's API token */
        partnerKey: string;
        /** the selected auth method */
        authMethod: AUTH_METHODS;
        /** The node environment to run on. */
        environment: ENVIRONMENT;
    }


interface CelsiusBalanceSummaryResponse {
        /** Contains user's balance per coin. **/
        balance: {
            [key: string]: number
        }
    }


interface CelsiusInterestSummaryResponse {
        /** Contains user's interest per coin. **/
        interest: {
            [key: string]: number
        }
    }


interface CelsiusStatisticsTotalUSDAmount {
        /** Contains total amount owned in usd. **/
        total_amount_usd: string,
    }


interface CelsiusAmountPerCoin {
        /** Contains, for each coin, amount of that coin and amount in usd. **/
        [key: string]: {
            amount: string,
            amount_usd: number
        }
    }


interface CelsiusStatisticsResponse {
        deposit_count: number | string,
        deposit_amount:  CelsiusStatisticsTotalUSDAmount & CelsiusAmountPerCoin,
        withdrawal_count: number | string,
        withdrawal_amount: CelsiusStatisticsTotalUSDAmount & CelsiusAmountPerCoin,
        interest_count: number | string,
        interest_amount: CelsiusStatisticsTotalUSDAmount & CelsiusAmountPerCoin
    }


interface CelsiusPaginationOptions {
        /** Page to retrieve. If left empty, defaults to first page.**/
        page?: number;
        /** How many records are shown per page. If left empty, defaults to 20 records.**/
        per_page?: number;
    }


interface CelsiusPagination {
        /** Total number of records */
        total?: number;
        /** Total number of pages */
        pages?: number;
        /** Current page */
        current?: number;
        /** How many records are shown per page */
        per_page?: number;
        /** A string representing with records are being shown */
        showing?: string;
    }


interface CelsiusCoinBalanceResponse {
        /** The amount in the current token */
        amount: string;
        /** The amount in US dollars of your token's balance */
        amount_in_usd: string;
    }


interface SupportedCountriesResponse {
        alpha2: string;
        alpha3: string;
        countryCallingCodes: string[];
        currencies: string[];
        emoji: string;
        ioc: string;
        languages: string[];
        name: string;
        status: string;
    }


interface KYCStatusResponse {
        status: string,
        reasons: object
    }


/**
     * Celsius Withdraw Options
     */
interface CelsiusWithdrawOptions {
        /** This is the withdrawal amount you want */
        amount: number;
        /** This is destination address that you want the tokens to be deposited  */
        address: string;
    }


/** Celsius Withdrawal Transaction, received in the response of the withdraw method */
interface CelsiusWithdrawalTransaction {
        /** Celsius Transaction ID received in the withdraw */
        tx_id: string|null;
        /** The state of the withdraw request */
        state: string;
    }


/**
     * Celsius Withdrawal Addresses
     */
interface CelsiusWithdrawalAddresses {
        addresses: {
            /** Each key,value pair represents a coin and the withdrawal address for that coin **/
            [key: string]: string
        };
    }


interface CelsiusTransactionRecord extends CelsiusCoinBalanceResponse {
        /** The amount in this coin rounded down to coin's decimals */
        amount: string;
        /** The amount in US dollars for this coin */
        amount_usd: string,
        /** The amount in this coin without any rounding applied **/
        amount_precise: string,
        /** The coin of the transaction */
        coin: string;
        /** In which state the transaction is in */
        state: string;
        /** The nature of the transaction */
        nature: string;
        /** The timestamp of the transaction */
        time: string;
        /** The transaction id in the blockchain. It's null if the transaction was not yet submitted */
        tx_id: string|null;
        /** Present only in transactions where nature is `interest`. Represents the original coin for which the interest has been accrued. **/
        original_interest_coin: string;
        /** Present only in transactions where nature is `interest`. Represents the amount accrued in `original_interest_coin`, before conversion to another asset. **/
        interest_amount_in_original_coin: string;
    }


/** Celsius transaction summary */
interface CelsiusTransactionSummary {
        /** Informations about the pagination */
        pagination: CelsiusPagination;
        /** Records of the transactions */
        record: CelsiusTransactionRecord[];
    }


interface KycStatus {
        status: 'PENDING' | 'COMPLETED' | 'PASSED' | 'REJECTED';
    }


interface CelsiusSupportedCurrencies {
        /** Short names of currencies **/
        currencies: string[]
    }


interface CelsiusKycFiles {
        /** Path to the file. **/
        document_front_image: string;
        /** Path to the file. **/
        document_back_image: string;
    }


interface User {
        id: string;
        auth0_user_id: string;
        email: string;
        pin: string;
        first_name: string;
        last_name: string;
        company_name: string;
        country: string;
        twitter_id: string;
        facebook_id: string;
        google_id: string;
        referral_link_id: string;
        twitter_screen_name: string;
        two_factor_secret: string;
        profile_picture: string;
        api_token: string;
        phone_number: string;
        citizenship: string;
        note: string;
        sms_verification_code: string;
        partner_id: string;
        blocked_reason: string;
        two_factor_enabled: boolean;
        phone_contacts_connected: boolean;
        whitelisted_by_location: boolean;
        twitter_friends_connected: boolean;
        facebook_friends_connected: boolean;
        expo_push_tokens: object;
        metadata: object;
        session_invalid_before: Date;
        created_at: Date;
        updated_at: Date;
        blocked_at: Date;
        kyc_status: KycStatus;
    }


interface CreateUser {
        first_name: string,
        last_name: string,
        middle_name?: string,
        email?: string,
        title?: string,
        date_of_birth: Date,
        citizenship: string,
        country: string,
        state?: string,
        city: string,
        zip: string,
        street: string,
        building_number?: string,
        flat_number?: string,
        itin?: string,
        national_id?: string,
        ssn?: string,
        gender: string,
        user_token: string
    }


interface UpdateUser {
        first_name: string,
        last_name: string,
        middle_name?: string,
        email?: string,
        title?: string,
        date_of_birth: Date,
        citizenship: string,
        country: string,
        state?: string,
        city: string,
        zip: string,
        street: string,
        building_number?: string,
        flat_number?: string,
        itin?: string,
        national_id?: string,
        ssn?: string,
        gender: string,
    }


interface UpdateEmail{
        email: string
    }


interface CreateUserResponse {
        userId: string,
        userToken: string
    }


interface CelsiusInstance {
        currencies: string[];
        getKycStatus(userSecret: string): Promise<KycStatus>;
        verifyKyc(userData: CelsiusKycUserData, documents: CelsiusKycFiles, userSecret: string): Promise<any>;
        getSupportedCurrencies(): Promise<CelsiusSupportedCurrencies>;
        getBalanceSummary(userSecret: string): Promise<CelsiusBalanceSummaryResponse>;
        getCoinBalance(coin: string, userSecret: string): Promise<CelsiusCoinBalanceResponse>;
        getInterestSummary(userSecret: string): Promise<CelsiusInterestSummaryResponse>;
        getTransactionSummary(pagination: CelsiusPaginationOptions, userSecret: string): Promise<CelsiusTransactionSummary>;
        getCoinTransactions(coin: string, pagination: CelsiusPaginationOptions, userSecret: string): Promise<CelsiusTransactionSummary>;
        getDeposit(coin: string, userSecret: string): Promise<{address: string}>;
        withdraw(coin: string, formFields: CelsiusWithdrawOptions, userSecret: string): Promise<{transaction_id: string}>;
        getWithdrawalAddressForCoin(coin: string, userSecret: string): Promise<{address: string}>
        getWithdrawalAddresses(userSecret: string): Promise<CelsiusWithdrawalAddresses>
        getTransactionStatus(transaction: string, userSecret: string): Promise<CelsiusWithdrawalTransaction>;
        getInterestRates(): Promise<InterestRates[]>
        getStatistics(userSecret: string, timestamp?: string): Promise<CelsiusStatisticsResponse>
        confirmTermsOfUse(termsOfUseId: string, confirmationDate: Date, userSecret: string): Promise<{success: boolean}>
        health(message: string): Promise<{originalMessage: string}>
        getSupportedCountries(userSecret:string): Promise<SupportedCountriesResponse[]>
        getKycVerificationStatus(userId:string, userSecret:string):Promise<KYCStatusResponse>
        startKycVerification(userId:string, documentType: string, userDocuments: CelsiusKycFiles, userSecret: string):Promise<{message: string}>
        createUser(user: CreateUser): Promise<CreateUserResponse>
        updateUser(userId:string, user:UpdateUser, userSecret: string):Promise<{status:boolean}>
        updateUserEmail(email:UpdateEmail, userSecret:string):Promise<{status:boolean}>
    }


interface InterestRates {
        interestRates: {
            coin: string;
            rate: string;
            currency: Currency;
        }
    }


interface Currency {
        id: number;
        name: string;
        short: string;
        image_url: string;
    }


interface ClassValidatorError {
        target: Object; // Object that was validated.
        property: string; // Object's property that haven't pass validation.
        value: any; // Value that haven't pass a validation.
        constraints?: { // Constraints that failed validation with error messages.
            [type: string]: string;
        };
        children?: ClassValidatorError[]; // Contains all nested validation errors of the property
    }


export enum AUTH_METHODS {
        API_KEY = 'api-key',
        USER_TOKEN = 'user-token',
    }


export enum ENVIRONMENT {
        STAGING = 'staging',
        PRODUCTION = 'production'
    }


params => {
                this._getReportCases();
                this._getColumns();
            }


(reportcases: any) => {
                    if (Number(reportcases.count) > 0) {
                        APP_UTILITIES.showToast('Info', reportcases.count + ' case(s) found.');
                        const max_records = Math.ceil(Number(reportcases.count) / 100) * 100;
                        this.page_size < 100 ? this.page_size = 100 : this.page_size = max_records;
                        this._prevPage = reportcases.previous;
                        this._nextPage = reportcases.next;
                        this.reportcases = reportcases.results;
                        this._sortAndShow();
                    } else {
                        APP_UTILITIES.showToast('Info', 'No cases found.');
                        this.notready = false;
                    }
                }


error => this._errorMessage = <any>error


@Component({
    templateUrl: 'report-detail.component.html'
})
export class ReportDaysToResolutionComponent implements OnInit {

    paginated = true;
    allow_filter = false;
    private _params: any;
    page_size = 100;
    private _prevPage: string;
    private _nextPage: string;
    reportcases: ReportCase[];
    columns: Column[];
    notready: Boolean = true;
    private _errorMessage: string;

    constructor (
        private _route: ActivatedRoute,
        private _reportCaseService: ReportCaseService,
    ) {}

    ngOnInit() {
        this._params = this._route.queryParams
            .subscribe(params => {
                this._getReportCases();
                this._getColumns();
            });
    }

    prevPage() {
        if (this._prevPage == null) {
            APP_UTILITIES.showToast('Info', 'This is the first page.');
        } else {
            this.notready = true;
            let prevPageNum;
            let ndxStart = this._prevPage.indexOf('page=');
            if (ndxStart === -1) {
                const urlSearchParams = {report: 'daystoresolution'};
                this._getReportCases(urlSearchParams);
            } else {
                ndxStart += 5;
                const ndxEnd = this._prevPage.indexOf('&', ndxStart);
                ndxEnd === -1 ? prevPageNum = this._prevPage.slice(ndxStart) : prevPageNum = this._prevPage.slice(ndxStart, ndxEnd);
                const urlSearchParams = {page: prevPageNum, report: 'daystoresolution'};
                this._getReportCases(urlSearchParams);
            }
        }
    }

    nextPage() {
        if (this._nextPage == null) {
            APP_UTILITIES.showToast('Info', 'This is the last page.');
        } else {
            this.notready = true;
            let nextPageNum;
            const ndxStart = this._nextPage.indexOf('page=') + 5;
            const ndxEnd = this._nextPage.indexOf('&', ndxStart);
            ndxEnd === -1 ? nextPageNum = this._nextPage.slice(ndxStart) : nextPageNum = this._nextPage.slice(ndxStart, ndxEnd);
            const urlSearchParams = {page: nextPageNum, report: 'daystoresolution'};
            this._getReportCases(urlSearchParams);
        }
    }

    exportToCSV(unit?: number) {
        this.notready = true;
        const urlSearchParams = 'report=daystoresolution&format=csv&page_size=' + this.page_size;
        this._getReportCasesCSV(urlSearchParams);
    }

    private _getReportCasesCSV(urlSearchParams?) {
        const self = this;
        this._reportCaseService.getReportCasesCSV(urlSearchParams)
            .then(function(data) {
                const blob = new Blob([data[0]], { type: 'text/csv' });
                FileSaver.saveAs(blob, data[1]);
                self.notready = false;
            });
    }

    private _getReportCases(newUrlSearchParams?) {
        const urlSearchParams = newUrlSearchParams ? newUrlSearchParams : {report: 'daystoresolution'};
        this._reportCaseService.getReportCases(urlSearchParams)
            .subscribe(
                (reportcases: any) => {
                    if (Number(reportcases.count) > 0) {
                        APP_UTILITIES.showToast('Info', reportcases.count + ' case(s) found.');
                        const max_records = Math.ceil(Number(reportcases.count) / 100) * 100;
                        this.page_size < 100 ? this.page_size = 100 : this.page_size = max_records;
                        this._prevPage = reportcases.previous;
                        this._nextPage = reportcases.next;
                        this.reportcases = reportcases.results;
                        this._sortAndShow();
                    } else {
                        APP_UTILITIES.showToast('Info', 'No cases found.');
                        this.notready = false;
                    }
                },
                error => this._errorMessage = <any>error
            );
    }

    private _getColumns() {
        this.columns = [
            new Column('id', 'Case ID'),
            new Column('case_reference', 'Case Reference'),
            new Column('request_date',  'Request Date'),
            new Column('close_date', 'Close Date'),
            new Column('close_days', 'Days to Close'),
        ];
    }

    private _sortAndShow() {
        this.reportcases.sort(APP_UTILITIES.dynamicSort('-close_days'));
        this.notready = false;
    }

    printCases() {
        window.print();
    }
}


ngOnInit() {
        this._params = this._route.queryParams
            .subscribe(params => {
                this._getReportCases();
                this._getColumns();
            });
    }


prevPage() {
        if (this._prevPage == null) {
            APP_UTILITIES.showToast('Info', 'This is the first page.');
        } else {
            this.notready = true;
            let prevPageNum;
            let ndxStart = this._prevPage.indexOf('page=');
            if (ndxStart === -1) {
                const urlSearchParams = {report: 'daystoresolution'};
                this._getReportCases(urlSearchParams);
            } else {
                ndxStart += 5;
                const ndxEnd = this._prevPage.indexOf('&', ndxStart);
                ndxEnd === -1 ? prevPageNum = this._prevPage.slice(ndxStart) : prevPageNum = this._prevPage.slice(ndxStart, ndxEnd);
                const urlSearchParams = {page: prevPageNum, report: 'daystoresolution'};
                this._getReportCases(urlSearchParams);
            }
        }
    }


nextPage() {
        if (this._nextPage == null) {
            APP_UTILITIES.showToast('Info', 'This is the last page.');
        } else {
            this.notready = true;
            let nextPageNum;
            const ndxStart = this._nextPage.indexOf('page=') + 5;
            const ndxEnd = this._nextPage.indexOf('&', ndxStart);
            ndxEnd === -1 ? nextPageNum = this._nextPage.slice(ndxStart) : nextPageNum = this._nextPage.slice(ndxStart, ndxEnd);
            const urlSearchParams = {page: nextPageNum, report: 'daystoresolution'};
            this._getReportCases(urlSearchParams);
        }
    }


exportToCSV(unit?: number) {
        this.notready = true;
        const urlSearchParams = 'report=daystoresolution&format=csv&page_size=' + this.page_size;
        this._getReportCasesCSV(urlSearchParams);
    }


private _getReportCasesCSV(urlSearchParams?) {
        const self = this;
        this._reportCaseService.getReportCasesCSV(urlSearchParams)
            .then(function(data) {
                const blob = new Blob([data[0]], { type: 'text/csv' });
                FileSaver.saveAs(blob, data[1]);
                self.notready = false;
            });
    }


private _getReportCases(newUrlSearchParams?) {
        const urlSearchParams = newUrlSearchParams ? newUrlSearchParams : {report: 'daystoresolution'};
        this._reportCaseService.getReportCases(urlSearchParams)
            .subscribe(
                (reportcases: any) => {
                    if (Number(reportcases.count) > 0) {
                        APP_UTILITIES.showToast('Info', reportcases.count + ' case(s) found.');
                        const max_records = Math.ceil(Number(reportcases.count) / 100) * 100;
                        this.page_size < 100 ? this.page_size = 100 : this.page_size = max_records;
                        this._prevPage = reportcases.previous;
                        this._nextPage = reportcases.next;
                        this.reportcases = reportcases.results;
                        this._sortAndShow();
                    } else {
                        APP_UTILITIES.showToast('Info', 'No cases found.');
                        this.notready = false;
                    }
                },
                error => this._errorMessage = <any>error
            );
    }


private _getColumns() {
        this.columns = [
            new Column('id', 'Case ID'),
            new Column('case_reference', 'Case Reference'),
            new Column('request_date',  'Request Date'),
            new Column('close_date', 'Close Date'),
            new Column('close_days', 'Days to Close'),
        ];
    }


private _sortAndShow() {
        this.reportcases.sort(APP_UTILITIES.dynamicSort('-close_days'));
        this.notready = false;
    }


printCases() {
        window.print();
    }


res =>
    {
      this.modalities = res.json()
        .map(modality => {
          return modality.name;
        });
      this.selectedModality = this.modalities[0];
    }


modality => {
          return modality.name;
        }


res =>
      {
        this.queryID = res.json().ID;
        this.app.toastJobResult(true, 'query', '/retrieve', this.queryID);
        this.router.navigate(['/retrieve', {id: this.queryID}]);
      }


()=> this.app.toastJobResult(false, 'query')


@Component
({
  selector: 'query-page',
  templateUrl: 'query.component.html',
  providers: [RESTService]
})

export class QueryComponent implements OnInit
{

  studyModalities = ['CR', 'CT', 'MR', 'NM', 'PT', 'US', 'XA'];
  nbCheckedModalities = 0;
  checkedModalities = [false, false, false, false, false, false, false];
  @Input() selectedModality: string;
  modalities: string;

  level = 'Study';

  accessionNumber = '';
  patientName = '';
  patientBirthDate = '';
  patientID = '';
  patientSex =  '';
  studyDate = '';
  studyDescription = '';
  modalitiesInStudy = ['*'];

  queryID: string;

  constructor(private permissions: PermissionsService, private service: RESTService, private router: Router, private app: AppComponent){}

  ngOnInit(): void
  {
    this.service.getModalities().then(res =>
    {
      this.modalities = res.json()
        .map(modality => {
          return modality.name;
        });
      this.selectedModality = this.modalities[0];
    });

  }

  /*
   * Check the checkbox of the study modality
   */
  checkModality(index: number): void
  {
    if(this.checkedModalities[index] == true)
      this.nbCheckedModalities--;
    else
      this.nbCheckedModalities++;
    this.checkedModalities[index] = !this.checkedModalities[index];
  }

  /*
   * Select the remote modality where to query from
   */
  selectModality(modality: string): void
  {
    this.selectedModality = modality;
  }

  /*
   * Validate the fields of the search and proceed to the query
   */
  ok(): void {
    if (this.accessionNumber == '')
      this.accessionNumber = '*';
    else
      this.accessionNumber = '*' + this.accessionNumber + '*';

    if (this.patientName == '')
      this.patientName = '*';
    else
      this.patientName = '*' + this.patientName + '*';

    if (this.patientID == '')
      this.patientID = '*';
    else
      this.patientID = '*' + this.patientID + '*';

    if (this.patientSex == '')
      this.patientSex = '*';
    else
      this.patientSex = '*' + this.patientSex + '*';

    if (this.patientBirthDate == '')
      this.patientBirthDate = '*';
    else
      this.patientBirthDate = '*' + this.patientBirthDate + '*';

    if (this.studyDescription == '')
      this.studyDescription = '*';
    else
      this.studyDescription = '*' + this.studyDescription + '*';

    if (this.studyDate == '')
      this.studyDate = '*';
    else
      this.studyDate = '*' + this.studyDate + '*';

    if(this.nbCheckedModalities > 0)
    {
      this.modalitiesInStudy = new Array<string>(this.nbCheckedModalities);
      let j = 0;
      for(let i = 0; i < this.studyModalities.length; i++)
      {
        if( this.checkedModalities[i] == true)
        {
          this.modalitiesInStudy[j] = this.studyModalities[i];
          j++;
        }
      }
      console.log(this.modalitiesInStudy);
    }

    this.service.getQueryID(this.selectedModality,
                                    this.level,
                                    this.accessionNumber,
                                    this.patientBirthDate,
                                    this.patientID,
                                    this.patientName,
                                    this.patientSex,
                                    this.studyDate,
                                    this.studyDescription,
                                    this.modalitiesInStudy).then(res =>
      {
        this.queryID = res.json().ID;
        this.app.toastJobResult(true, 'query', '/retrieve', this.queryID);
        this.router.navigate(['/retrieve', {id: this.queryID}]);
      }, ()=> this.app.toastJobResult(false, 'query'));
    this.resetFields();
    this.app.toastInfo('jobRegistered');
  }

  /*
  Reset the fields of the research panel.
   */
  resetFields()
  {
    this.accessionNumber = '';
    this.patientName = '';
    this.patientBirthDate = '';
    this.patientID = '';
    this.patientSex =  '';
    this.studyDate = '';
    this.studyDescription = '';
    this.modalitiesInStudy = ['*'];

    this.nbCheckedModalities = 0;
    this.checkedModalities = [false, false, false, false, false, false, false];
  }
}


ngOnInit(): void
  {
    this.service.getModalities().then(res =>
    {
      this.modalities = res.json()
        .map(modality => {
          return modality.name;
        });
      this.selectedModality = this.modalities[0];
    });

  }


/*
   * Check the checkbox of the study modality
   */
checkModality(index: number): void
  {
    if(this.checkedModalities[index] == true)
      this.nbCheckedModalities--;
    else
      this.nbCheckedModalities++;
    this.checkedModalities[index] = !this.checkedModalities[index];
  }


/*
   * Select the remote modality where to query from
   */
selectModality(modality: string): void
  {
    this.selectedModality = modality;
  }


/*
   * Validate the fields of the search and proceed to the query
   */
ok(): void {
    if (this.accessionNumber == '')
      this.accessionNumber = '*';
    else
      this.accessionNumber = '*' + this.accessionNumber + '*';

    if (this.patientName == '')
      this.patientName = '*';
    else
      this.patientName = '*' + this.patientName + '*';

    if (this.patientID == '')
      this.patientID = '*';
    else
      this.patientID = '*' + this.patientID + '*';

    if (this.patientSex == '')
      this.patientSex = '*';
    else
      this.patientSex = '*' + this.patientSex + '*';

    if (this.patientBirthDate == '')
      this.patientBirthDate = '*';
    else
      this.patientBirthDate = '*' + this.patientBirthDate + '*';

    if (this.studyDescription == '')
      this.studyDescription = '*';
    else
      this.studyDescription = '*' + this.studyDescription + '*';

    if (this.studyDate == '')
      this.studyDate = '*';
    else
      this.studyDate = '*' + this.studyDate + '*';

    if(this.nbCheckedModalities > 0)
    {
      this.modalitiesInStudy = new Array<string>(this.nbCheckedModalities);
      let j = 0;
      for(let i = 0; i < this.studyModalities.length; i++)
      {
        if( this.checkedModalities[i] == true)
        {
          this.modalitiesInStudy[j] = this.studyModalities[i];
          j++;
        }
      }
      console.log(this.modalitiesInStudy);
    }

    this.service.getQueryID(this.selectedModality,
                                    this.level,
                                    this.accessionNumber,
                                    this.patientBirthDate,
                                    this.patientID,
                                    this.patientName,
                                    this.patientSex,
                                    this.studyDate,
                                    this.studyDescription,
                                    this.modalitiesInStudy).then(res =>
      {
        this.queryID = res.json().ID;
        this.app.toastJobResult(true, 'query', '/retrieve', this.queryID);
        this.router.navigate(['/retrieve', {id: this.queryID}]);
      }, ()=> this.app.toastJobResult(false, 'query'));
    this.resetFields();
    this.app.toastInfo('jobRegistered');
  }


/*
  Reset the fields of the research panel.
   */
resetFields()
  {
    this.accessionNumber = '';
    this.patientName = '';
    this.patientBirthDate = '';
    this.patientID = '';
    this.patientSex =  '';
    this.studyDate = '';
    this.studyDescription = '';
    this.modalitiesInStudy = ['*'];

    this.nbCheckedModalities = 0;
    this.checkedModalities = [false, false, false, false, false, false, false];
  }


function withSplitLinesCollection(text: string, callback: (model: TextModel, linesCollection: ViewModelLinesFromProjectedModel) => void): void {
		const config = new TestConfiguration({});
		const wrappingInfo = config.options.get(EditorOption.wrappingInfo);
		const fontInfo = config.options.get(EditorOption.fontInfo);
		const wordWrapBreakAfterCharacters = config.options.get(EditorOption.wordWrapBreakAfterCharacters);
		const wordWrapBreakBeforeCharacters = config.options.get(EditorOption.wordWrapBreakBeforeCharacters);
		const wrappingIndent = config.options.get(EditorOption.wrappingIndent);

		const lineBreaksComputerFactory = new MonospaceLineBreaksComputerFactory(wordWrapBreakBeforeCharacters, wordWrapBreakAfterCharacters);

		const model = createTextModel([
			'int main() {',
			'\tprintf("Hello world!");',
			'}',
			'int main() {',
			'\tprintf("Hello world!");',
			'}',
		].join('\n'));

		const linesCollection = new ViewModelLinesFromProjectedModel(
			1,
			model,
			lineBreaksComputerFactory,
			lineBreaksComputerFactory,
			fontInfo,
			model.getOptions().tabSize,
			'simple',
			wrappingInfo.wrappingColumn,
			wrappingIndent
		);

		callback(model, linesCollection);

		linesCollection.dispose();
		model.dispose();
		config.dispose();
	}


function assertViewLineTokens(_actual: IViewLineTokens, expected: ITestViewLineToken[]): void {
		let actual: ITestViewLineToken[] = [];
		for (let i = 0, len = _actual.getCount(); i < len; i++) {
			actual[i] = {
				endIndex: _actual.getEndOffset(i),
				value: _actual.getForeground(i)
			};
		}
		assert.deepStrictEqual(actual, expected);
	}


function assertMinimapLineRenderingData(actual: ViewLineData, expected: ITestMinimapLineRenderingData | null): void {
		if (actual === null && expected === null) {
			assert.ok(true);
			return;
		}
		if (expected === null) {
			assert.ok(false);
		}
		assert.strictEqual(actual.content, expected.content);
		assert.strictEqual(actual.minColumn, expected.minColumn);
		assert.strictEqual(actual.maxColumn, expected.maxColumn);
		assertViewLineTokens(actual.tokens, expected.tokens);
	}


function assertMinimapLinesRenderingData(actual: ViewLineData[], expected: Array<ITestMinimapLineRenderingData | null>): void {
		assert.strictEqual(actual.length, expected.length);
		for (let i = 0; i < expected.length; i++) {
			assertMinimapLineRenderingData(actual[i], expected[i]);
		}
	}


function assertAllMinimapLinesRenderingData(splitLinesCollection: ViewModelLinesFromProjectedModel, all: ITestMinimapLineRenderingData[]): void {
		let lineCount = all.length;
		for (let line = 1; line <= lineCount; line++) {
			assert.strictEqual(splitLinesCollection.getViewLineData(line).content, splitLinesCollection.getViewLineContent(line));
		}

		for (let start = 1; start <= lineCount; start++) {
			for (let end = start; end <= lineCount; end++) {
				let count = end - start + 1;
				for (let desired = Math.pow(2, count) - 1; desired >= 0; desired--) {
					let needed: boolean[] = [];
					let expected: Array<ITestMinimapLineRenderingData | null> = [];
					for (let i = 0; i < count; i++) {
						needed[i] = (desired & (1 << i)) ? true : false;
						expected[i] = (needed[i] ? all[start - 1 + i] : null);
					}
					let actual = splitLinesCollection.getViewLinesData(start, end, needed);

					assertMinimapLinesRenderingData(actual, expected);
					// Comment out next line to test all possible combinations
					break;
				}
			}
		}
	}


function withSplitLinesCollection(model: TextModel, wordWrap: 'on' | 'off' | 'wordWrapColumn' | 'bounded', wordWrapColumn: number, callback: (splitLinesCollection: ViewModelLinesFromProjectedModel) => void): void {
		const configuration = new TestConfiguration({
			wordWrap: wordWrap,
			wordWrapColumn: wordWrapColumn,
			wrappingIndent: 'indent'
		});
		const wrappingInfo = configuration.options.get(EditorOption.wrappingInfo);
		const fontInfo = configuration.options.get(EditorOption.fontInfo);
		const wordWrapBreakAfterCharacters = configuration.options.get(EditorOption.wordWrapBreakAfterCharacters);
		const wordWrapBreakBeforeCharacters = configuration.options.get(EditorOption.wordWrapBreakBeforeCharacters);
		const wrappingIndent = configuration.options.get(EditorOption.wrappingIndent);

		const lineBreaksComputerFactory = new MonospaceLineBreaksComputerFactory(wordWrapBreakBeforeCharacters, wordWrapBreakAfterCharacters);

		const linesCollection = new ViewModelLinesFromProjectedModel(
			1,
			model,
			lineBreaksComputerFactory,
			lineBreaksComputerFactory,
			fontInfo,
			model.getOptions().tabSize,
			'simple',
			wrappingInfo.wrappingColumn,
			wrappingIndent
		);

		callback(linesCollection);

		configuration.dispose();
	}


function pos(lineNumber: number, column: number): Position {
	return new Position(lineNumber, column);
}


function createSplitLine(splitLengths: number[], breakingOffsetsVisibleColumn: number[], wrappedTextIndentWidth: number, isVisible: boolean = true): IModelLineProjection {
	return createModelLineProjection(createLineBreakData(splitLengths, breakingOffsetsVisibleColumn, wrappedTextIndentWidth), isVisible);
}


function createLineBreakData(breakingLengths: number[], breakingOffsetsVisibleColumn: number[], wrappedTextIndentWidth: number): ModelLineProjectionData {
	let sums: number[] = [];
	for (let i = 0; i < breakingLengths.length; i++) {
		sums[i] = (i > 0 ? sums[i - 1] : 0) + breakingLengths[i];
	}
	return new ModelLineProjectionData(null, null, sums, breakingOffsetsVisibleColumn, wrappedTextIndentWidth);
}


function createModel(text: string): ISimpleModel {
	return {
		tokenization: {
			getLineTokens: (lineNumber: number) => {
				return null!;
			},
		},
		getLineContent: (lineNumber: number) => {
			return text;
		},
		getLineLength: (lineNumber: number) => {
			return text.length;
		},
		getLineMinColumn: (lineNumber: number) => {
			return 1;
		},
		getLineMaxColumn: (lineNumber: number) => {
			return text.length + 1;
		},
		getValueInRange: (range: IRange, eol?: EndOfLinePreference) => {
			return text.substring(range.startColumn - 1, range.endColumn - 1);
		}
	};
}


() => {
		let model1 = createModel('My First LineMy Second LineAnd another one');
		let line1 = createSplitLine([13, 14, 15], [13, 13 + 14, 13 + 14 + 15], 0);

		assert.strictEqual(line1.getViewLineCount(), 3);
		assert.strictEqual(line1.getViewLineContent(model1, 1, 0), 'My First Line');
		assert.strictEqual(line1.getViewLineContent(model1, 1, 1), 'My Second Line');
		assert.strictEqual(line1.getViewLineContent(model1, 1, 2), 'And another one');
		assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 0), 14);
		assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 1), 15);
		assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 2), 16);
		for (let col = 1; col <= 14; col++) {
			assert.strictEqual(line1.getModelColumnOfViewPosition(0, col), col, 'getInputColumnOfOutputPosition(0, ' + col + ')');
		}
		for (let col = 1; col <= 15; col++) {
			assert.strictEqual(line1.getModelColumnOfViewPosition(1, col), 13 + col, 'getInputColumnOfOutputPosition(1, ' + col + ')');
		}
		for (let col = 1; col <= 16; col++) {
			assert.strictEqual(line1.getModelColumnOfViewPosition(2, col), 13 + 14 + col, 'getInputColumnOfOutputPosition(2, ' + col + ')');
		}
		for (let col = 1; col <= 13; col++) {
			assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(0, col), 'getOutputPositionOfInputPosition(' + col + ')');
		}
		for (let col = 1 + 13; col <= 14 + 13; col++) {
			assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(1, col - 13), 'getOutputPositionOfInputPosition(' + col + ')');
		}
		for (let col = 1 + 13 + 14; col <= 15 + 14 + 13; col++) {
			assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(2, col - 13 - 14), 'getOutputPositionOfInputPosition(' + col + ')');
		}

		model1 = createModel('My First LineMy Second LineAnd another one');
		line1 = createSplitLine([13, 14, 15], [13, 13 + 14, 13 + 14 + 15], 4);

		assert.strictEqual(line1.getViewLineCount(), 3);
		assert.strictEqual(line1.getViewLineContent(model1, 1, 0), 'My First Line');
		assert.strictEqual(line1.getViewLineContent(model1, 1, 1), '    My Second Line');
		assert.strictEqual(line1.getViewLineContent(model1, 1, 2), '    And another one');
		assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 0), 14);
		assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 1), 19);
		assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 2), 20);

		let actualViewColumnMapping: number[][] = [];
		for (let lineIndex = 0; lineIndex < line1.getViewLineCount(); lineIndex++) {
			let actualLineViewColumnMapping: number[] = [];
			for (let col = 1; col <= line1.getViewLineMaxColumn(model1, 1, lineIndex); col++) {
				actualLineViewColumnMapping.push(line1.getModelColumnOfViewPosition(lineIndex, col));
			}
			actualViewColumnMapping.push(actualLineViewColumnMapping);
		}
		assert.deepStrictEqual(actualViewColumnMapping, [
			[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
			[14, 14, 14, 14, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28],
			[28, 28, 28, 28, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43],
		]);

		for (let col = 1; col <= 13; col++) {
			assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(0, col), '6.getOutputPositionOfInputPosition(' + col + ')');
		}
		for (let col = 1 + 13; col <= 14 + 13; col++) {
			assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(1, 4 + col - 13), '7.getOutputPositionOfInputPosition(' + col + ')');
		}
		for (let col = 1 + 13 + 14; col <= 15 + 14 + 13; col++) {
			assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(2, 4 + col - 13 - 14), '8.getOutputPositionOfInputPosition(' + col + ')');
		}
	}


() => {

		const text = [
			'int main() {',
			'\tprintf("Hello world!");',
			'}',
			'int main() {',
			'\tprintf("Hello world!");',
			'}',
		].join('\n');

		withSplitLinesCollection(text, (model, linesCollection) => {
			assert.strictEqual(linesCollection.getViewLineCount(), 6);

			// getOutputIndentGuide
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(-1, -1), [0]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(0, 0), [0]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(1, 1), [0]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(2, 2), [1]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(3, 3), [0]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(4, 4), [0]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(5, 5), [1]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(6, 6), [0]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(7, 7), [0]);

			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(0, 7), [0, 1, 0, 0, 1, 0]);

			// getOutputLineContent
			assert.strictEqual(linesCollection.getViewLineContent(-1), 'int main() {');
			assert.strictEqual(linesCollection.getViewLineContent(0), 'int main() {');
			assert.strictEqual(linesCollection.getViewLineContent(1), 'int main() {');
			assert.strictEqual(linesCollection.getViewLineContent(2), '\tprintf("Hello world!");');
			assert.strictEqual(linesCollection.getViewLineContent(3), '}');
			assert.strictEqual(linesCollection.getViewLineContent(4), 'int main() {');
			assert.strictEqual(linesCollection.getViewLineContent(5), '\tprintf("Hello world!");');
			assert.strictEqual(linesCollection.getViewLineContent(6), '}');
			assert.strictEqual(linesCollection.getViewLineContent(7), '}');

			// getOutputLineMinColumn
			assert.strictEqual(linesCollection.getViewLineMinColumn(-1), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(0), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(1), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(2), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(3), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(4), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(5), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(6), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(7), 1);

			// getOutputLineMaxColumn
			assert.strictEqual(linesCollection.getViewLineMaxColumn(-1), 13);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(0), 13);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(1), 13);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(2), 25);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(3), 2);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(4), 13);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(5), 25);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(6), 2);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(7), 2);

			// convertOutputPositionToInputPosition
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(-1, 1), new Position(1, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(0, 1), new Position(1, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(1, 1), new Position(1, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(2, 1), new Position(2, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(3, 1), new Position(3, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(4, 1), new Position(4, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(5, 1), new Position(5, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(6, 1), new Position(6, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(7, 1), new Position(6, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(8, 1), new Position(6, 1));
		});
	}


(model, linesCollection) => {
			assert.strictEqual(linesCollection.getViewLineCount(), 6);

			// getOutputIndentGuide
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(-1, -1), [0]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(0, 0), [0]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(1, 1), [0]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(2, 2), [1]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(3, 3), [0]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(4, 4), [0]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(5, 5), [1]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(6, 6), [0]);
			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(7, 7), [0]);

			assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(0, 7), [0, 1, 0, 0, 1, 0]);

			// getOutputLineContent
			assert.strictEqual(linesCollection.getViewLineContent(-1), 'int main() {');
			assert.strictEqual(linesCollection.getViewLineContent(0), 'int main() {');
			assert.strictEqual(linesCollection.getViewLineContent(1), 'int main() {');
			assert.strictEqual(linesCollection.getViewLineContent(2), '\tprintf("Hello world!");');
			assert.strictEqual(linesCollection.getViewLineContent(3), '}');
			assert.strictEqual(linesCollection.getViewLineContent(4), 'int main() {');
			assert.strictEqual(linesCollection.getViewLineContent(5), '\tprintf("Hello world!");');
			assert.strictEqual(linesCollection.getViewLineContent(6), '}');
			assert.strictEqual(linesCollection.getViewLineContent(7), '}');

			// getOutputLineMinColumn
			assert.strictEqual(linesCollection.getViewLineMinColumn(-1), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(0), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(1), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(2), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(3), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(4), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(5), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(6), 1);
			assert.strictEqual(linesCollection.getViewLineMinColumn(7), 1);

			// getOutputLineMaxColumn
			assert.strictEqual(linesCollection.getViewLineMaxColumn(-1), 13);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(0), 13);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(1), 13);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(2), 25);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(3), 2);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(4), 13);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(5), 25);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(6), 2);
			assert.strictEqual(linesCollection.getViewLineMaxColumn(7), 2);

			// convertOutputPositionToInputPosition
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(-1, 1), new Position(1, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(0, 1), new Position(1, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(1, 1), new Position(1, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(2, 1), new Position(2, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(3, 1), new Position(3, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(4, 1), new Position(4, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(5, 1), new Position(5, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(6, 1), new Position(6, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(7, 1), new Position(6, 1));
			assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(8, 1), new Position(6, 1));
		}


() => {

		const text = [
			'int main() {',
			'\tprintf("Hello world!");',
			'}',
			'int main() {',
			'\tprintf("Hello world!");',
			'}',
		].join('\n');

		withSplitLinesCollection(text, (model, linesCollection) => {
			linesCollection.setHiddenAreas([
				new Range(1, 1, 3, 1),
				new Range(5, 1, 6, 1)
			]);

			let viewLineCount = linesCollection.getViewLineCount();
			assert.strictEqual(viewLineCount, 1, 'getOutputLineCount()');

			let modelLineCount = model.getLineCount();
			for (let lineNumber = 0; lineNumber <= modelLineCount + 1; lineNumber++) {
				let lineMinColumn = (lineNumber >= 1 && lineNumber <= modelLineCount) ? model.getLineMinColumn(lineNumber) : 1;
				let lineMaxColumn = (lineNumber >= 1 && lineNumber <= modelLineCount) ? model.getLineMaxColumn(lineNumber) : 1;
				for (let column = lineMinColumn - 1; column <= lineMaxColumn + 1; column++) {
					let viewPosition = linesCollection.convertModelPositionToViewPosition(lineNumber, column);

					// validate view position
					let viewLineNumber = viewPosition.lineNumber;
					let viewColumn = viewPosition.column;
					if (viewLineNumber < 1) {
						viewLineNumber = 1;
					}
					let lineCount = linesCollection.getViewLineCount();
					if (viewLineNumber > lineCount) {
						viewLineNumber = lineCount;
					}
					let viewMinColumn = linesCollection.getViewLineMinColumn(viewLineNumber);
					let viewMaxColumn = linesCollection.getViewLineMaxColumn(viewLineNumber);
					if (viewColumn < viewMinColumn) {
						viewColumn = viewMinColumn;
					}
					if (viewColumn > viewMaxColumn) {
						viewColumn = viewMaxColumn;
					}
					let validViewPosition = new Position(viewLineNumber, viewColumn);
					assert.strictEqual(viewPosition.toString(), validViewPosition.toString(), 'model->view for ' + lineNumber + ', ' + column);
				}
			}

			for (let lineNumber = 0; lineNumber <= viewLineCount + 1; lineNumber++) {
				let lineMinColumn = linesCollection.getViewLineMinColumn(lineNumber);
				let lineMaxColumn = linesCollection.getViewLineMaxColumn(lineNumber);
				for (let column = lineMinColumn - 1; column <= lineMaxColumn + 1; column++) {
					let modelPosition = linesCollection.convertViewPositionToModelPosition(lineNumber, column);
					let validModelPosition = model.validatePosition(modelPosition);
					assert.strictEqual(modelPosition.toString(), validModelPosition.toString(), 'view->model for ' + lineNumber + ', ' + column);
				}
			}
		});
	}


(model, linesCollection) => {
			linesCollection.setHiddenAreas([
				new Range(1, 1, 3, 1),
				new Range(5, 1, 6, 1)
			]);

			let viewLineCount = linesCollection.getViewLineCount();
			assert.strictEqual(viewLineCount, 1, 'getOutputLineCount()');

			let modelLineCount = model.getLineCount();
			for (let lineNumber = 0; lineNumber <= modelLineCount + 1; lineNumber++) {
				let lineMinColumn = (lineNumber >= 1 && lineNumber <= modelLineCount) ? model.getLineMinColumn(lineNumber) : 1;
				let lineMaxColumn = (lineNumber >= 1 && lineNumber <= modelLineCount) ? model.getLineMaxColumn(lineNumber) : 1;
				for (let column = lineMinColumn - 1; column <= lineMaxColumn + 1; column++) {
					let viewPosition = linesCollection.convertModelPositionToViewPosition(lineNumber, column);

					// validate view position
					let viewLineNumber = viewPosition.lineNumber;
					let viewColumn = viewPosition.column;
					if (viewLineNumber < 1) {
						viewLineNumber = 1;
					}
					let lineCount = linesCollection.getViewLineCount();
					if (viewLineNumber > lineCount) {
						viewLineNumber = lineCount;
					}
					let viewMinColumn = linesCollection.getViewLineMinColumn(viewLineNumber);
					let viewMaxColumn = linesCollection.getViewLineMaxColumn(viewLineNumber);
					if (viewColumn < viewMinColumn) {
						viewColumn = viewMinColumn;
					}
					if (viewColumn > viewMaxColumn) {
						viewColumn = viewMaxColumn;
					}
					let validViewPosition = new Position(viewLineNumber, viewColumn);
					assert.strictEqual(viewPosition.toString(), validViewPosition.toString(), 'model->view for ' + lineNumber + ', ' + column);
				}
			}

			for (let lineNumber = 0; lineNumber <= viewLineCount + 1; lineNumber++) {
				let lineMinColumn = linesCollection.getViewLineMinColumn(lineNumber);
				let lineMaxColumn = linesCollection.getViewLineMaxColumn(lineNumber);
				for (let column = lineMinColumn - 1; column <= lineMaxColumn + 1; column++) {
					let modelPosition = linesCollection.convertViewPositionToModelPosition(lineNumber, column);
					let validModelPosition = model.validatePosition(modelPosition);
					assert.strictEqual(modelPosition.toString(), validModelPosition.toString(), 'view->model for ' + lineNumber + ', ' + column);
				}
			}
		}


() => {
		let _lineIndex = 0;
		const tokenizationSupport: languages.ITokenizationSupport = {
			getInitialState: () => NullState,
			tokenize: undefined!,
			tokenizeEncoded: (line: string, hasEOL: boolean, state: languages.IState): languages.EncodedTokenizationResult => {
				let tokens = _tokens[_lineIndex++];

				let result = new Uint32Array(2 * tokens.length);
				for (let i = 0; i < tokens.length; i++) {
					result[2 * i] = tokens[i].startIndex;
					result[2 * i + 1] = (
						tokens[i].value << MetadataConsts.FOREGROUND_OFFSET
					);
				}
				return new languages.EncodedTokenizationResult(result, state);
			}
		};
		const LANGUAGE_ID = 'modelModeTest1';
		languageRegistration = languages.TokenizationRegistry.register(LANGUAGE_ID, tokenizationSupport);
		model = createTextModel(_text.join('\n'), LANGUAGE_ID);
		// force tokenization
		model.tokenization.forceTokenization(model.getLineCount());
	}


() => NullState


(line: string, hasEOL: boolean, state: languages.IState): languages.EncodedTokenizationResult => {
				let tokens = _tokens[_lineIndex++];

				let result = new Uint32Array(2 * tokens.length);
				for (let i = 0; i < tokens.length; i++) {
					result[2 * i] = tokens[i].startIndex;
					result[2 * i + 1] = (
						tokens[i].value << MetadataConsts.FOREGROUND_OFFSET
					);
				}
				return new languages.EncodedTokenizationResult(result, state);
			}


() => {
		model.dispose();
		languageRegistration.dispose();
	}


() => {
		withSplitLinesCollection(model, 'off', 0, (splitLinesCollection) => {
			assert.strictEqual(splitLinesCollection.getViewLineCount(), 8);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true);

			let _expected: ITestMinimapLineRenderingData[] = [
				{
					content: 'class Nice {',
					minColumn: 1,
					maxColumn: 13,
					tokens: [
						{ endIndex: 5, value: 1 },
						{ endIndex: 6, value: 2 },
						{ endIndex: 10, value: 3 },
						{ endIndex: 12, value: 4 },
					]
				},
				{
					content: '	function hi() {',
					minColumn: 1,
					maxColumn: 17,
					tokens: [
						{ endIndex: 1, value: 5 },
						{ endIndex: 9, value: 6 },
						{ endIndex: 10, value: 7 },
						{ endIndex: 12, value: 8 },
						{ endIndex: 16, value: 9 },
					]
				},
				{
					content: '		console.log("Hello world");',
					minColumn: 1,
					maxColumn: 30,
					tokens: [
						{ endIndex: 2, value: 10 },
						{ endIndex: 9, value: 11 },
						{ endIndex: 10, value: 12 },
						{ endIndex: 13, value: 13 },
						{ endIndex: 14, value: 14 },
						{ endIndex: 27, value: 15 },
						{ endIndex: 29, value: 16 },
					]
				},
				{
					content: '	}',
					minColumn: 1,
					maxColumn: 3,
					tokens: [
						{ endIndex: 2, value: 17 },
					]
				},
				{
					content: '	function hello() {',
					minColumn: 1,
					maxColumn: 20,
					tokens: [
						{ endIndex: 1, value: 18 },
						{ endIndex: 9, value: 19 },
						{ endIndex: 10, value: 20 },
						{ endIndex: 15, value: 21 },
						{ endIndex: 19, value: 22 },
					]
				},
				{
					content: '		console.log("Hello world, this is a somewhat longer line");',
					minColumn: 1,
					maxColumn: 62,
					tokens: [
						{ endIndex: 2, value: 23 },
						{ endIndex: 9, value: 24 },
						{ endIndex: 10, value: 25 },
						{ endIndex: 13, value: 26 },
						{ endIndex: 14, value: 27 },
						{ endIndex: 59, value: 28 },
						{ endIndex: 61, value: 29 },
					]
				},
				{
					minColumn: 1,
					maxColumn: 3,
					content: '	}',
					tokens: [
						{ endIndex: 2, value: 30 },
					]
				},
				{
					minColumn: 1,
					maxColumn: 2,
					content: '}',
					tokens: [
						{ endIndex: 1, value: 31 },
					]
				}
			];

			assertAllMinimapLinesRenderingData(splitLinesCollection, [
				_expected[0],
				_expected[1],
				_expected[2],
				_expected[3],
				_expected[4],
				_expected[5],
				_expected[6],
				_expected[7],
			]);

			splitLinesCollection.setHiddenAreas([new Range(2, 1, 4, 1)]);
			assert.strictEqual(splitLinesCollection.getViewLineCount(), 5);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), false);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), false);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), false);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true);

			assertAllMinimapLinesRenderingData(splitLinesCollection, [
				_expected[0],
				_expected[4],
				_expected[5],
				_expected[6],
				_expected[7],
			]);
		});
	}


(splitLinesCollection) => {
			assert.strictEqual(splitLinesCollection.getViewLineCount(), 8);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true);

			let _expected: ITestMinimapLineRenderingData[] = [
				{
					content: 'class Nice {',
					minColumn: 1,
					maxColumn: 13,
					tokens: [
						{ endIndex: 5, value: 1 },
						{ endIndex: 6, value: 2 },
						{ endIndex: 10, value: 3 },
						{ endIndex: 12, value: 4 },
					]
				},
				{
					content: '	function hi() {',
					minColumn: 1,
					maxColumn: 17,
					tokens: [
						{ endIndex: 1, value: 5 },
						{ endIndex: 9, value: 6 },
						{ endIndex: 10, value: 7 },
						{ endIndex: 12, value: 8 },
						{ endIndex: 16, value: 9 },
					]
				},
				{
					content: '		console.log("Hello world");',
					minColumn: 1,
					maxColumn: 30,
					tokens: [
						{ endIndex: 2, value: 10 },
						{ endIndex: 9, value: 11 },
						{ endIndex: 10, value: 12 },
						{ endIndex: 13, value: 13 },
						{ endIndex: 14, value: 14 },
						{ endIndex: 27, value: 15 },
						{ endIndex: 29, value: 16 },
					]
				},
				{
					content: '	}',
					minColumn: 1,
					maxColumn: 3,
					tokens: [
						{ endIndex: 2, value: 17 },
					]
				},
				{
					content: '	function hello() {',
					minColumn: 1,
					maxColumn: 20,
					tokens: [
						{ endIndex: 1, value: 18 },
						{ endIndex: 9, value: 19 },
						{ endIndex: 10, value: 20 },
						{ endIndex: 15, value: 21 },
						{ endIndex: 19, value: 22 },
					]
				},
				{
					content: '		console.log("Hello world, this is a somewhat longer line");',
					minColumn: 1,
					maxColumn: 62,
					tokens: [
						{ endIndex: 2, value: 23 },
						{ endIndex: 9, value: 24 },
						{ endIndex: 10, value: 25 },
						{ endIndex: 13, value: 26 },
						{ endIndex: 14, value: 27 },
						{ endIndex: 59, value: 28 },
						{ endIndex: 61, value: 29 },
					]
				},
				{
					minColumn: 1,
					maxColumn: 3,
					content: '	}',
					tokens: [
						{ endIndex: 2, value: 30 },
					]
				},
				{
					minColumn: 1,
					maxColumn: 2,
					content: '}',
					tokens: [
						{ endIndex: 1, value: 31 },
					]
				}
			];

			assertAllMinimapLinesRenderingData(splitLinesCollection, [
				_expected[0],
				_expected[1],
				_expected[2],
				_expected[3],
				_expected[4],
				_expected[5],
				_expected[6],
				_expected[7],
			]);

			splitLinesCollection.setHiddenAreas([new Range(2, 1, 4, 1)]);
			assert.strictEqual(splitLinesCollection.getViewLineCount(), 5);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), false);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), false);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), false);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true);

			assertAllMinimapLinesRenderingData(splitLinesCollection, [
				_expected[0],
				_expected[4],
				_expected[5],
				_expected[6],
				_expected[7],
			]);
		}


() => {
		withSplitLinesCollection(model, 'wordWrapColumn', 30, (splitLinesCollection) => {
			assert.strictEqual(splitLinesCollection.getViewLineCount(), 12);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true);

			let _expected: ITestMinimapLineRenderingData[] = [
				{
					content: 'class Nice {',
					minColumn: 1,
					maxColumn: 13,
					tokens: [
						{ endIndex: 5, value: 1 },
						{ endIndex: 6, value: 2 },
						{ endIndex: 10, value: 3 },
						{ endIndex: 12, value: 4 },
					]
				},
				{
					content: '	function hi() {',
					minColumn: 1,
					maxColumn: 17,
					tokens: [
						{ endIndex: 1, value: 5 },
						{ endIndex: 9, value: 6 },
						{ endIndex: 10, value: 7 },
						{ endIndex: 12, value: 8 },
						{ endIndex: 16, value: 9 },
					]
				},
				{
					content: '		console.log("Hello ',
					minColumn: 1,
					maxColumn: 22,
					tokens: [
						{ endIndex: 2, value: 10 },
						{ endIndex: 9, value: 11 },
						{ endIndex: 10, value: 12 },
						{ endIndex: 13, value: 13 },
						{ endIndex: 14, value: 14 },
						{ endIndex: 21, value: 15 },
					]
				},
				{
					content: '            world");',
					minColumn: 13,
					maxColumn: 21,
					tokens: [
						{ endIndex: 18, value: 15 },
						{ endIndex: 20, value: 16 },
					]
				},
				{
					content: '	}',
					minColumn: 1,
					maxColumn: 3,
					tokens: [
						{ endIndex: 2, value: 17 },
					]
				},
				{
					content: '	function hello() {',
					minColumn: 1,
					maxColumn: 20,
					tokens: [
						{ endIndex: 1, value: 18 },
						{ endIndex: 9, value: 19 },
						{ endIndex: 10, value: 20 },
						{ endIndex: 15, value: 21 },
						{ endIndex: 19, value: 22 },
					]
				},
				{
					content: '		console.log("Hello ',
					minColumn: 1,
					maxColumn: 22,
					tokens: [
						{ endIndex: 2, value: 23 },
						{ endIndex: 9, value: 24 },
						{ endIndex: 10, value: 25 },
						{ endIndex: 13, value: 26 },
						{ endIndex: 14, value: 27 },
						{ endIndex: 21, value: 28 },
					]
				},
				{
					content: '            world, this is a ',
					minColumn: 13,
					maxColumn: 30,
					tokens: [
						{ endIndex: 29, value: 28 },
					]
				},
				{
					content: '            somewhat longer ',
					minColumn: 13,
					maxColumn: 29,
					tokens: [
						{ endIndex: 28, value: 28 },
					]
				},
				{
					content: '            line");',
					minColumn: 13,
					maxColumn: 20,
					tokens: [
						{ endIndex: 17, value: 28 },
						{ endIndex: 19, value: 29 },
					]
				},
				{
					content: '	}',
					minColumn: 1,
					maxColumn: 3,
					tokens: [
						{ endIndex: 2, value: 30 },
					]
				},
				{
					content: '}',
					minColumn: 1,
					maxColumn: 2,
					tokens: [
						{ endIndex: 1, value: 31 },
					]
				}
			];

			assertAllMinimapLinesRenderingData(splitLinesCollection, [
				_expected[0],
				_expected[1],
				_expected[2],
				_expected[3],
				_expected[4],
				_expected[5],
				_expected[6],
				_expected[7],
				_expected[8],
				_expected[9],
				_expected[10],
				_expected[11],
			]);

			splitLinesCollection.setHiddenAreas([new Range(2, 1, 4, 1)]);
			assert.strictEqual(splitLinesCollection.getViewLineCount(), 8);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), false);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), false);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), false);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true);

			assertAllMinimapLinesRenderingData(splitLinesCollection, [
				_expected[0],
				_expected[5],
				_expected[6],
				_expected[7],
				_expected[8],
				_expected[9],
				_expected[10],
				_expected[11],
			]);
		});
	}


(splitLinesCollection) => {
			assert.strictEqual(splitLinesCollection.getViewLineCount(), 12);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true);

			let _expected: ITestMinimapLineRenderingData[] = [
				{
					content: 'class Nice {',
					minColumn: 1,
					maxColumn: 13,
					tokens: [
						{ endIndex: 5, value: 1 },
						{ endIndex: 6, value: 2 },
						{ endIndex: 10, value: 3 },
						{ endIndex: 12, value: 4 },
					]
				},
				{
					content: '	function hi() {',
					minColumn: 1,
					maxColumn: 17,
					tokens: [
						{ endIndex: 1, value: 5 },
						{ endIndex: 9, value: 6 },
						{ endIndex: 10, value: 7 },
						{ endIndex: 12, value: 8 },
						{ endIndex: 16, value: 9 },
					]
				},
				{
					content: '		console.log("Hello ',
					minColumn: 1,
					maxColumn: 22,
					tokens: [
						{ endIndex: 2, value: 10 },
						{ endIndex: 9, value: 11 },
						{ endIndex: 10, value: 12 },
						{ endIndex: 13, value: 13 },
						{ endIndex: 14, value: 14 },
						{ endIndex: 21, value: 15 },
					]
				},
				{
					content: '            world");',
					minColumn: 13,
					maxColumn: 21,
					tokens: [
						{ endIndex: 18, value: 15 },
						{ endIndex: 20, value: 16 },
					]
				},
				{
					content: '	}',
					minColumn: 1,
					maxColumn: 3,
					tokens: [
						{ endIndex: 2, value: 17 },
					]
				},
				{
					content: '	function hello() {',
					minColumn: 1,
					maxColumn: 20,
					tokens: [
						{ endIndex: 1, value: 18 },
						{ endIndex: 9, value: 19 },
						{ endIndex: 10, value: 20 },
						{ endIndex: 15, value: 21 },
						{ endIndex: 19, value: 22 },
					]
				},
				{
					content: '		console.log("Hello ',
					minColumn: 1,
					maxColumn: 22,
					tokens: [
						{ endIndex: 2, value: 23 },
						{ endIndex: 9, value: 24 },
						{ endIndex: 10, value: 25 },
						{ endIndex: 13, value: 26 },
						{ endIndex: 14, value: 27 },
						{ endIndex: 21, value: 28 },
					]
				},
				{
					content: '            world, this is a ',
					minColumn: 13,
					maxColumn: 30,
					tokens: [
						{ endIndex: 29, value: 28 },
					]
				},
				{
					content: '            somewhat longer ',
					minColumn: 13,
					maxColumn: 29,
					tokens: [
						{ endIndex: 28, value: 28 },
					]
				},
				{
					content: '            line");',
					minColumn: 13,
					maxColumn: 20,
					tokens: [
						{ endIndex: 17, value: 28 },
						{ endIndex: 19, value: 29 },
					]
				},
				{
					content: '	}',
					minColumn: 1,
					maxColumn: 3,
					tokens: [
						{ endIndex: 2, value: 30 },
					]
				},
				{
					content: '}',
					minColumn: 1,
					maxColumn: 2,
					tokens: [
						{ endIndex: 1, value: 31 },
					]
				}
			];

			assertAllMinimapLinesRenderingData(splitLinesCollection, [
				_expected[0],
				_expected[1],
				_expected[2],
				_expected[3],
				_expected[4],
				_expected[5],
				_expected[6],
				_expected[7],
				_expected[8],
				_expected[9],
				_expected[10],
				_expected[11],
			]);

			splitLinesCollection.setHiddenAreas([new Range(2, 1, 4, 1)]);
			assert.strictEqual(splitLinesCollection.getViewLineCount(), 8);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), false);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), false);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), false);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true);
			assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true);

			assertAllMinimapLinesRenderingData(splitLinesCollection, [
				_expected[0],
				_expected[5],
				_expected[6],
				_expected[7],
				_expected[8],
				_expected[9],
				_expected[10],
				_expected[11],
			]);
		}