// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
// Package excelize providing a set of functions that allow you to write to
// and read from XLSX files. Support reads and writes XLSX file generated by
// Microsoft Excel™ 2007 and later. Support save file without losing original
// charts of XLSX. This library needs Go version 1.10 or later.

package excelize

// SheetPrOption is an option of a view of a worksheet. See SetSheetPrOptions().
type SheetPrOption interface {
	setSheetPrOption(view *xlsxSheetPr)
}

// SheetPrOptionPtr is a writable SheetPrOption. See GetSheetPrOptions().
type SheetPrOptionPtr interface {
	SheetPrOption
	getSheetPrOption(view *xlsxSheetPr)
}

type (
	// CodeName is a SheetPrOption
	CodeName string
	// EnableFormatConditionsCalculation is a SheetPrOption
	EnableFormatConditionsCalculation bool
	// Published is a SheetPrOption
	Published bool
	// FitToPage is a SheetPrOption
	FitToPage bool
	// AutoPageBreaks is a SheetPrOption
	AutoPageBreaks bool
	// OutlineSummaryBelow is an outlinePr, within SheetPr option
	OutlineSummaryBelow bool
)

// setSheetPrOption implements the SheetPrOption interface.
func (o OutlineSummaryBelow) setSheetPrOption(pr *xlsxSheetPr) {
	if pr.OutlinePr == nil {
		pr.OutlinePr = new(xlsxOutlinePr)
	}
	pr.OutlinePr.SummaryBelow = bool(o)
}

// getSheetPrOption implements the SheetPrOptionPtr interface.
func (o *OutlineSummaryBelow) getSheetPrOption(pr *xlsxSheetPr) {
	// Excel default: true
	if pr == nil || pr.OutlinePr == nil {
		*o = true
		return
	}
	*o = OutlineSummaryBelow(defaultTrue(&pr.OutlinePr.SummaryBelow))
}

// setSheetPrOption implements the SheetPrOption interface and specifies a
// stable name of the sheet.
func (o CodeName) setSheetPrOption(pr *xlsxSheetPr) {
	pr.CodeName = string(o)
}

// getSheetPrOption implements the SheetPrOptionPtr interface and get the
// stable name of the sheet.
func (o *CodeName) getSheetPrOption(pr *xlsxSheetPr) {
	if pr == nil {
		*o = ""
		return
	}
	*o = CodeName(pr.CodeName)
}

// setSheetPrOption implements the SheetPrOption interface and flag indicating
// whether the conditional formatting calculations shall be evaluated.
func (o EnableFormatConditionsCalculation) setSheetPrOption(pr *xlsxSheetPr) {
	pr.EnableFormatConditionsCalculation = boolPtr(bool(o))
}

// getSheetPrOption implements the SheetPrOptionPtr interface and get the
// settings of whether the conditional formatting calculations shall be
// evaluated.
func (o *EnableFormatConditionsCalculation) getSheetPrOption(pr *xlsxSheetPr) {
	if pr == nil {
		*o = true
		return
	}
	*o = EnableFormatConditionsCalculation(defaultTrue(pr.EnableFormatConditionsCalculation))
}

// setSheetPrOption implements the SheetPrOption interface and flag indicating
// whether the worksheet is published.
func (o Published) setSheetPrOption(pr *xlsxSheetPr) {
	pr.Published = boolPtr(bool(o))
}

// getSheetPrOption implements the SheetPrOptionPtr interface and get the
// settings of whether the worksheet is published.
func (o *Published) getSheetPrOption(pr *xlsxSheetPr) {
	if pr == nil {
		*o = true
		return
	}
	*o = Published(defaultTrue(pr.Published))
}

// setSheetPrOption implements the SheetPrOption interface.
func (o FitToPage) setSheetPrOption(pr *xlsxSheetPr) {
	if pr.PageSetUpPr == nil {
		if !o {
			return
		}
		pr.PageSetUpPr = new(xlsxPageSetUpPr)
	}
	pr.PageSetUpPr.FitToPage = bool(o)
}

// getSheetPrOption implements the SheetPrOptionPtr interface.
func (o *FitToPage) getSheetPrOption(pr *xlsxSheetPr) {
	// Excel default: false
	if pr == nil || pr.PageSetUpPr == nil {
		*o = false
		return
	}
	*o = FitToPage(pr.PageSetUpPr.FitToPage)
}

// setSheetPrOption implements the SheetPrOption interface.
func (o AutoPageBreaks) setSheetPrOption(pr *xlsxSheetPr) {
	if pr.PageSetUpPr == nil {
		if !o {
			return
		}
		pr.PageSetUpPr = new(xlsxPageSetUpPr)
	}
	pr.PageSetUpPr.AutoPageBreaks = bool(o)
}

// getSheetPrOption implements the SheetPrOptionPtr interface.
func (o *AutoPageBreaks) getSheetPrOption(pr *xlsxSheetPr) {
	// Excel default: false
	if pr == nil || pr.PageSetUpPr == nil {
		*o = false
		return
	}
	*o = AutoPageBreaks(pr.PageSetUpPr.AutoPageBreaks)
}

// SetSheetPrOptions provides a function to sets worksheet properties.
//
// Available options:
//   CodeName(string)
//   EnableFormatConditionsCalculation(bool)
//   Published(bool)
//   FitToPage(bool)
//   AutoPageBreaks(bool)
//   OutlineSummaryBelow(bool)
func (f *File) SetSheetPrOptions(name string, opts ...SheetPrOption) error {
	sheet, err := f.workSheetReader(name)
	if err != nil {
		return err
	}
	pr := sheet.SheetPr
	if pr == nil {
		pr = new(xlsxSheetPr)
		sheet.SheetPr = pr
	}

	for _, opt := range opts {
		opt.setSheetPrOption(pr)
	}
	return err
}

// GetSheetPrOptions provides a function to gets worksheet properties.
//
// Available options:
//   CodeName(string)
//   EnableFormatConditionsCalculation(bool)
//   Published(bool)
//   FitToPage(bool)
//   AutoPageBreaks(bool)
//   OutlineSummaryBelow(bool)
func (f *File) GetSheetPrOptions(name string, opts ...SheetPrOptionPtr) error {
	sheet, err := f.workSheetReader(name)
	if err != nil {
		return err
	}
	pr := sheet.SheetPr

	for _, opt := range opts {
		opt.getSheetPrOption(pr)
	}
	return err
}
