/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
import assert from 'assert';
import { getCompressedContent, IJSONSchema } from '../../common/jsonSchema.js';
import { ensureNoDisposablesAreLeakedInTestSuite } from './utils.js';

suite('JSON Schema', () => {

	ensureNoDisposablesAreLeakedInTestSuite();

	test('getCompressedContent 1', () => {

		const schema: IJSONSchema = {
			type: 'object',
			properties: {
				a: {
					type: 'object',
					description: 'a',
					properties: {
						b: {
							type: 'object',
							properties: {
								c: {
									type: 'object',
									properties: {
										d: {
											type: 'string'
										}
									}
								}
							}
						}
					}
				},
				e: {
					type: 'object',
					description: 'e',
					properties: {
						b: {
							type: 'object',
							properties: {
								c: {
									type: 'object',
									properties: {
										d: {
											type: 'string'
										}
									}
								}
							}
						}
					}
				}
			}
		};

		const expected: IJSONSchema = {
			type: 'object',
			properties: {
				a: {
					type: 'object',
					description: 'a',
					properties: {
						b: {
							$ref: '#/$defs/_0'
						}
					}
				},
				e: {
					type: 'object',
					description: 'e',
					properties: {
						b: {
							$ref: '#/$defs/_0'
						}
					}
				}
			},
			$defs: {
				"_0": {
					type: 'object',
					properties: {
						c: {
							type: 'object',
							properties: {
								d: {
									type: 'string'
								}
							}
						}
					}
				}
			}

		};

		assert.deepEqual(getCompressedContent(schema), JSON.stringify(expected));
	});

	test('getCompressedContent 2', () => {

		const schema: IJSONSchema = {
			type: 'object',
			properties: {
				a: {
					type: 'object',
					properties: {
						b: {
							type: 'object',
							properties: {
								c: {
									type: 'object',
									properties: {
										d: {
											type: 'string'
										}
									}
								}
							}
						}
					}
				},
				e: {
					type: 'object',
					properties: {
						b: {
							type: 'object',
							properties: {
								c: {
									type: 'object',
									properties: {
										d: {
											type: 'string'
										}
									}
								}
							}
						}
					}
				}
			}
		};

		const expected: IJSONSchema = {
			type: 'object',
			properties: {
				a: {
					$ref: '#/$defs/_0'

				},
				e: {
					$ref: '#/$defs/_0'
				}
			},
			$defs: {
				"_0": {
					type: 'object',
					properties: {
						b: {
							type: 'object',
							properties: {
								c: {
									type: 'object',
									properties: {
										d: {
											type: 'string'
										}
									}
								}
							}
						}
					}
				}
			}

		};

		assert.deepEqual(getCompressedContent(schema), JSON.stringify(expected));
	});

	test('getCompressedContent 3', () => {


		const schema: IJSONSchema = {
			type: 'object',
			properties: {
				a: {
					type: 'object',
					oneOf: [
						{
							allOf: [
								{
									properties: {
										name: {
											type: 'string'
										},
										description: {
											type: 'string'
										}
									}
								},
								{
									properties: {
										street: {
											type: 'string'
										},
									}
								}
							]
						},
						{
							allOf: [
								{
									properties: {
										name: {
											type: 'string'
										},
										description: {
											type: 'string'
										}
									}
								},
								{
									properties: {
										river: {
											type: 'string'
										},
									}
								}
							]
						},
						{
							allOf: [
								{
									properties: {
										name: {
											type: 'string'
										},
										description: {
											type: 'string'
										}
									}
								},
								{
									properties: {
										mountain: {
											type: 'string'
										},
									}
								}
							]
						}
					]
				},
				b: {
					type: 'object',
					properties: {
						street: {
							properties: {
								street: {
									type: 'string'
								}
							}
						}
					}
				}
			}
		};

		const expected: IJSONSchema = {
			"type": "object",
			"properties": {
				"a": {
					"type": "object",
					"oneOf": [
						{
							"allOf": [
								{
									"$ref": "#/$defs/_0"
								},
								{
									"$ref": "#/$defs/_1"
								}
							]
						},
						{
							"allOf": [
								{
									"$ref": "#/$defs/_0"
								},
								{
									"properties": {
										"river": {
											"type": "string"
										}
									}
								}
							]
						},
						{
							"allOf": [
								{
									"$ref": "#/$defs/_0"
								},
								{
									"properties": {
										"mountain": {
											"type": "string"
										}
									}
								}
							]
						}
					]
				},
				"b": {
					"type": "object",
					"properties": {
						"street": {
							"$ref": "#/$defs/_1"
						}
					}
				}
			},
			"$defs": {
				"_0": {
					"properties": {
						"name": {
							"type": "string"
						},
						"description": {
							"type": "string"
						}
					}
				},
				"_1": {
					"properties": {
						"street": {
							"type": "string"
						}
					}
				}
			}
		};

		const actual = getCompressedContent(schema);
		assert.deepEqual(actual, JSON.stringify(expected));
	});

	test('getCompressedContent 4', () => {

		const schema: IJSONSchema = {
			type: 'object',
			properties: {
				a: {
					type: 'object',
					properties: {
						b: {
							type: 'object',
							properties: {
								c: {
									type: 'object',
									properties: {
										d: {
											type: 'string'
										}
									}
								}
							}
						}
					}
				},
				e: {
					type: 'object',
					properties: {
						b: {
							type: 'object',
							properties: {
								c: {
									type: 'object',
									properties: {
										d: {
											type: 'string'
										}
									}
								}
							}
						}
					}
				},
				f: {
					type: 'object',
					properties: {
						d: {
							type: 'string'
						}
					}
				}
			}
		};

		const expected: IJSONSchema = {
			type: 'object',
			properties: {
				a: {
					$ref: '#/$defs/_0'
				},
				e: {
					$ref: '#/$defs/_0'
				},
				f: {
					$ref: '#/$defs/_1'
				}
			},
			$defs: {
				"_0": {
					type: 'object',
					properties: {
						b: {
							type: 'object',
							properties: {
								c: {
									$ref: '#/$defs/_1'
								}
							}
						}
					}
				},
				"_1": {
					type: 'object',
					properties: {
						d: {
							type: 'string'
						}
					}
				}
			}

		};

		assert.deepEqual(getCompressedContent(schema), JSON.stringify(expected));
	});

	test('getCompressedContent 5', () => {

		const schema: IJSONSchema = {
			type: 'object',
			properties: {
				a: {
					type: 'array',
					items: {
						type: 'object',
						properties: {
							c: {
								type: 'object',
								properties: {
									d: {
										type: 'string'
									}
								}
							}
						}
					}
				},
				e: {
					type: 'array',
					items: {
						type: 'object',
						properties: {
							c: {
								type: 'object',
								properties: {
									d: {
										type: 'string'
									}
								}
							}
						}
					}
				},
				f: {
					type: 'object',
					properties: {
						b: {
							type: 'object',
							properties: {
								c: {
									type: 'object',
									properties: {
										d: {
											type: 'string'
										}
									}
								}
							}
						}
					}
				},
				g: {
					type: 'object',
					properties: {
						b: {
							type: 'object',
							properties: {
								c: {
									type: 'object',
									properties: {
										d: {
											type: 'string'
										}
									}
								}
							}
						}
					}
				}
			}
		};

		const expected: IJSONSchema = {
			type: 'object',
			properties: {
				a: {
					$ref: '#/$defs/_0'
				},
				e: {
					$ref: '#/$defs/_0'
				},
				f: {
					$ref: '#/$defs/_1'
				},
				g: {
					$ref: '#/$defs/_1'
				}
			},
			$defs: {
				"_0": {
					type: 'array',
					items: {
						$ref: '#/$defs/_2'
					}
				},
				"_1": {
					type: 'object',
					properties: {
						b: {
							$ref: '#/$defs/_2'
						}
					}
				},
				"_2": {
					type: 'object',
					properties: {
						c: {
							type: 'object',
							properties: {
								d: {
									type: 'string'
								}
							}
						}
					}
				}
			}

		};

		assert.deepEqual(getCompressedContent(schema), JSON.stringify(expected));
	});


});
