/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package flash

import (
	"fmt"
	"sort"
)

const FLASH_AREA_NAME_BOOTLOADER = "FLASH_AREA_BOOTLOADER"
const FLASH_AREA_NAME_IMAGE_0 = "FLASH_AREA_IMAGE_0"
const FLASH_AREA_NAME_IMAGE_1 = "FLASH_AREA_IMAGE_1"
const FLASH_AREA_NAME_IMAGE_SCRATCH = "FLASH_AREA_IMAGE_SCRATCH"
const AREA_USER_ID_MIN = 16

var SYSTEM_AREA_NAME_ID_MAP = map[string]int{
	FLASH_AREA_NAME_BOOTLOADER:    0,
	FLASH_AREA_NAME_IMAGE_0:       1,
	FLASH_AREA_NAME_IMAGE_1:       2,
	FLASH_AREA_NAME_IMAGE_SCRATCH: 3,
}

type FlashArea struct {
	Name   string `json:"name"`
	Id     int    `json:"id"`
	Device int    `json:"device"`
	Offset int    `json:"offset"`
	Size   int    `json:"size"`
}

type areaOffSorter struct {
	areas []FlashArea
}

func (s areaOffSorter) Len() int {
	return len(s.areas)
}
func (s areaOffSorter) Swap(i, j int) {
	s.areas[i], s.areas[j] = s.areas[j], s.areas[i]
}
func (s areaOffSorter) Less(i, j int) bool {
	ai := s.areas[i]
	aj := s.areas[j]

	if ai.Device < aj.Device {
		return true
	}
	if ai.Device > aj.Device {
		return false
	}
	return ai.Offset < aj.Offset
}

func SortFlashAreasByDevOff(areas []FlashArea) []FlashArea {
	sorter := areaOffSorter{
		areas: make([]FlashArea, len(areas)),
	}

	for i, a := range areas {
		sorter.areas[i] = a
	}

	sort.Sort(sorter)
	return sorter.areas
}

func SortFlashAreasById(areas []FlashArea) []FlashArea {
	idMap := make(map[int]FlashArea, len(areas))
	ids := make([]int, 0, len(areas))
	for _, area := range areas {
		idMap[area.Id] = area
		ids = append(ids, area.Id)
	}
	sort.Ints(ids)

	sorted := make([]FlashArea, len(ids))
	for i, id := range ids {
		sorted[i] = idMap[id]
	}

	return sorted
}

func areasDistinct(a FlashArea, b FlashArea) bool {
	if a.Device != b.Device {
		return true
	}

	var lo FlashArea
	var hi FlashArea

	if a.Offset < b.Offset {
		lo = a
		hi = b
	} else {
		lo = b
		hi = a
	}

	return lo.Offset+lo.Size <= hi.Offset
}

// @return overlapping-areas, id-conflicts.
func DetectErrors(areas []FlashArea) ([][]FlashArea, [][]FlashArea) {
	var overlaps [][]FlashArea
	var conflicts [][]FlashArea

	for i := 0; i < len(areas)-1; i++ {
		iarea := areas[i]
		for j := i + 1; j < len(areas); j++ {
			jarea := areas[j]

			if !areasDistinct(iarea, jarea) {
				overlaps = append(overlaps, []FlashArea{iarea, jarea})
			}

			if iarea.Id == jarea.Id {
				conflicts = append(conflicts, []FlashArea{iarea, jarea})
			}
		}
	}

	return overlaps, conflicts
}

func ErrorText(overlaps [][]FlashArea, conflicts [][]FlashArea) string {
	str := ""

	if len(conflicts) > 0 {
		str += "Conflicting flash area IDs detected:\n"

		for _, pair := range conflicts {
			str += fmt.Sprintf("    (%d) %s =/= %s\n",
				pair[0].Id-AREA_USER_ID_MIN, pair[0].Name, pair[1].Name)
		}
	}

	if len(overlaps) > 0 {
		str += "Overlapping flash areas detected:\n"

		for _, pair := range overlaps {
			str += fmt.Sprintf("    %s =/= %s\n", pair[0].Name, pair[1].Name)
		}
	}

	return str
}
