package diff

import (
	"github.com/pingcap/errors"
	"github.com/pingcap/log"
	"github.com/pingcap/tidb/parser/model"
	"go.uber.org/zap"
	"sort"
	"strings"
)

// IndexFields wraps the column info for the user config "index-fields".
type IndexFields struct {
	cols      []*model.ColumnInfo
	tableInfo *model.TableInfo
	empty     bool
}

func indexFieldsFromConfigString(strFields string, tableInfo *model.TableInfo) (*IndexFields, error) {
	if len(strFields) == 0 {
		// Empty option
		return &IndexFields{empty: true}, nil
	}

	if tableInfo == nil {
		log.Panic("parsing index fields with empty tableInfo",
			zap.String("index-fields", strFields))
	}

	splitFieldArr := strings.Split(strFields, ",")
	for i := range splitFieldArr {
		splitFieldArr[i] = strings.TrimSpace(splitFieldArr[i])
	}

	fields, err := getSplitFields(tableInfo, splitFieldArr)
	if err != nil {
		return nil, errors.Trace(err)
	}

	// Sort the columns to help with comparison.
	sortColsInPlace(fields)

	return &IndexFields{
		cols:      fields,
		tableInfo: tableInfo,
	}, nil
}

func (f *IndexFields) MatchesIndex(index *model.IndexInfo) bool {
	if f.empty {
		// Default config matches all.
		return true
	}

	// Sanity checks.
	if index == nil {
		log.Panic("matching with empty index")
	}
	if len(f.cols) == 0 {
		log.Panic("unexpected cols with length 0")
	}

	if len(index.Columns) != len(f.cols) {
		// We need an exact match.
		// Lengths not matching eliminates the possibility.
		return false
	}

	indexCols := getColumnsFromIndex(index, f.tableInfo)
	// Sort for comparison
	sortColsInPlace(indexCols)

	for i := 0; i < len(indexCols); i++ {
		if f.cols[i].ID != indexCols[i].ID {
			return false
		}
	}

	return true
}

func (f *IndexFields) Cols() []*model.ColumnInfo {
	return f.cols
}

// IsEmpty returns true if the struct represents an empty
// user-configured "index-fields" option.
func (f *IndexFields) IsEmpty() bool {
	return f.empty
}

func sortColsInPlace(cols []*model.ColumnInfo) {
	sort.SliceStable(cols, func(i, j int) bool {
		return cols[i].ID < cols[j].ID
	})
}
