<template>
	<nav v-if="show">
		<ul
			v-if="type === 'abbreviated'"
			:class="paginationClass">
			<datatable-button
				v-if="page - 3 >= 1"
				:value="1"
				@click="setPageNum" />
			<datatable-button
				v-if="page - 4 >= 1"
				disabled>
				...
			</datatable-button>

			<datatable-button
				v-if="page - 2 >= 1"
				:value="page - 2"
				@click="setPageNum" />
			<datatable-button
				v-if="page - 1 >= 1"
				:value="page - 1"
				@click="setPageNum" />

			<datatable-button
				:value="page"
				selected />

			<datatable-button
				v-if="page + 1 <= totalPages"
				:value="page + 1"
				@click="setPageNum" />
			<datatable-button
				v-if="page + 2 <= totalPages"
				:value="page + 2"
				@click="setPageNum" />

			<datatable-button
				v-if="page + 4 <= totalPages"
				disabled>
				...
			</datatable-button>
			<datatable-button
				v-if="page + 3 <= totalPages"
				:value="totalPages"
				@click="setPageNum" />
		</ul>
		<ul
			v-else-if="type === 'long'"
			:class="paginationClass">
			<datatable-button
				v-for="i in totalPages"
				:key="i"
				:value="i"
				:selected="i === page"
				@click="setPageNum" />
		</ul>
		<ul
			v-else-if="type === 'short'"
			:class="paginationClass">
			<datatable-button
				v-if="page > 1"
				:value="page - 1"
				@click="setPageNum">
				<span v-html="previousIcon" />
			</datatable-button>
			<datatable-button
				:value="page"
				selected />
			<datatable-button
				v-if="page < totalPages"
				:value="page + 1"
				@click="setPageNum">
				<span v-html="nextIcon" />
			</datatable-button>
		</ul>
	</nav>
</template>

<script>
/**
 * The component that is used to manage & change pages on a {@link datatable}.
 * 
 * @module datatable-pager
 * 
 * @vue-prop {string} [table = 'default']                       - The id of the associated {@link datatable}.
 * @vue-prop {'long' | 'short' | 'abbreviated'} [type = 'long'] - The kind of the pager
 * @vue-prop {number} [perPage = 10]                            - Max number of items to display.
 * @vue-prop {number} [page = 1]                                - The page index to display
 * 
 * @vue-data {datatable | null} tableInstance - Reference to the associated {@link datatable} through the {@link datatable-pager#table} prop.
 * 
 * @vue-computed {boolean} show               - Returns `true` if the pager has an associated {@link datatable} with some rows.
 * @vue-computed {number} totalRows           - The total number of rows in the associated {@link datatable}.
 * @vue-computed {string} paginationClass     - HTML class on the wrapping `ul` around the pager buttons.
 * @vue-computed {string} disabledClass       - HTML class to apply on disabled buttons. (unused).
 * @vue-computed {string} previousLinkClasses - HTML class to apply on the previous page's button. (unused).
 * @vue-computed {string} nextLinkClasses     - HTML class to apply on the next page's button. (unused).
 * @vue-computed {number} totalPages          - The total number of pages in the associated {@link datatable}.
 * @vue-computed {string} previousIcon        - HTML content of the previous page's button.
 * @vue-computed {string} nextIcon            - HTML content of the next page's button.
 * @vue-computed {Settings} settings          - Reference to the {@link Settings} object linked to this pager type.
 */
export default {
	model: {
		prop:  'page',
		event: 'change',
	},
	props: {
		table: {
			type:    String,
			default: 'default',
		},
		type: {
			type:    String,
			default: 'long',
		},
		perPage: {
			type:    Number,
			default: 10,
		},
		page: {
			type:    Number,
			default: 1,
		},
	},
	data: () => ( {
		tableInstance: null,
	} ),
	computed: {
		show(){
			return this.tableInstance && this.totalRows > 0;
		},
		totalRows(){
			if ( this.tableInstance ){
				return this.tableInstance.totalRows;
			}

			return 0;
		},
		paginationClass(){
			return this.settings.get( 'pager.classes.pager' );
		},
		totalPages(){
			if ( this.totalRows <= 0 || this.perPage <= 0 ){
				return null;
			}

			return Math.ceil( this.totalRows / this.perPage );
		},
		previousIcon(){
			return this.settings.get( 'pager.icons.previous' );
		},
		nextIcon(){
			return this.settings.get( 'pager.icons.next' );
		},
		settings(){
			return this.$options.settings;
		},
	},
	watch: {
		totalRows(){
			if ( this.page > this.totalPages ){
				this.setPageNum( this.totalPages );
			}
		},
		perPage(){
			// Skip change if no need to change page
			if ( this.page <= this.totalPages ){
				return;
			}

			this.setPageNum( this.totalPages );
		},
	},
	created(){
		// Try to link with table
		if ( !this.linkWithTable( this.table ) ){
			// If it fail, bind next tables initialization
			const tableReadyHandler = tableName => {
				// If it is the correct table and linking is OK...
				if ( tableName === this.table && this.linkWithTable( tableName ) ){
					// Unbind table initializations
					this.$root.$off( 'table.ready', tableReadyHandler );
				}
			};
			this.$root.$on( 'table.ready', tableReadyHandler );
		}
	},
	methods: {
		/**
		 * Link the pager with the table, assign to the table some properties, and trigger an event on the table.
		 * 
		 * @emits Datatable#table.pager-bound
		 * @param {string} tableName - The name of the table to bind the pager with.
		 * @returns {boolean} `true` if the link is succesfull, or `false` if it could not find a table to associate with.
		 */
		linkWithTable( tableName ){
			if ( this.$datatables && this.$datatables[tableName] ){
				const targetTable = this.$datatables[tableName];
				this.tableInstance = targetTable;
				targetTable.perPage = this.perPage;
				targetTable.pagers.push( this );
				targetTable.$emit( 'table.pager-bound', this );
				return true;
			} else {
				return false;
			}
		},
		/**
		 * Defines the page index to display.
		 *
		 * @emits change
		 * @param {number} pageIndex - The new page index.
		 * @returns {void} Nothing.
		 */
		setPageNum( pageIndex ){
			this.tableInstance.page = pageIndex;
			this.tableInstance.perPage = this.perPage;

			this.$emit( 'change', pageIndex );
		},
	},
	settings: null,
};
</script>