/**
 * 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 mfg

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"

	"github.com/apache/mynewt-artifact/errors"
	"github.com/apache/mynewt-artifact/flash"
	"github.com/apache/mynewt-artifact/image"
	"github.com/apache/mynewt-artifact/manifest"
	"github.com/apache/mynewt-artifact/mfg"
	"mynewt.apache.org/newt/newt/builder"
	"mynewt.apache.org/newt/newt/flashmap"
	"mynewt.apache.org/newt/newt/parse"
	"mynewt.apache.org/newt/newt/pkg"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/newt/target"
	"mynewt.apache.org/newt/util"
)

type MfgBuildTarget struct {
	Target        *target.Target
	Area          flash.FlashArea
	Offset        int
	Size          int
	IsBoot        bool
	BinPath       string
	ExtraManifest map[string]interface{}
}

type MfgBuildRaw struct {
	Filename      string
	Offset        int
	Size          int
	Area          flash.FlashArea
	ExtraFiles    []string
	ExtraManifest map[string]interface{}
}

type MfgBuildMetaMmr struct {
	Area flash.FlashArea
}

type MfgBuildMeta struct {
	Area     flash.FlashArea
	Hash     bool
	FlashMap bool
	Mmrs     []MfgBuildMetaMmr
}

// Can be used to construct an Mfg object.
type MfgBuilder struct {
	BasePkg     *pkg.LocalPackage
	Bsp         *pkg.BspPackage
	Targets     []MfgBuildTarget
	Raws        []MfgBuildRaw
	Meta        *MfgBuildMeta
	BaseAddress int
}

// Searches the provided flash map for the named area.
func lookUpArea(fm flashmap.FlashMap, name string) (flash.FlashArea, error) {
	area, ok := fm.Areas[name]
	if !ok {
		return flash.FlashArea{}, util.FmtNewtError(
			"reference to undefined flash area \"%s\"", name)
	}

	return area, nil
}

// Searches the project for the target corresponding to the specified decoded
// entry (read from `mfg.yml`).
func lookUpTarget(dt DecodedTarget) (*target.Target, error) {
	t := target.GetTargets()[dt.Name]
	if t == nil {
		return nil, util.FmtNewtError(
			"target entry references undefined target \"%s\"", dt.Name)
	}

	return t, nil
}

func normalizeOffset(offset int, length int,
	area flash.FlashArea, baseAddress int) (int, error) {

	areaEnd := area.Offset + area.Size - baseAddress
	if offset == OFFSET_END {
		if length > area.Size {
			return 0, util.FmtNewtError(
				"segment is too large to fit in flash area \"%s\"; "+
					"segment=%d, area=%d", area.Name, length, area.Size)
		}
		return areaEnd - length, nil
	}

	if offset+length > area.Size {
		return 0, util.FmtNewtError(
			"segment extends beyond end of flash area \"%s\"; "+
				"offset=%d len=%d area_len=%d",
			area.Name, offset, length, area.Size)
	}

	return (area.Offset + offset - baseAddress), nil
}

func calcBsp(dm DecodedMfg,
	basePkg *pkg.LocalPackage) (*pkg.BspPackage, error) {

	var bspLpkg *pkg.LocalPackage
	bspMap := map[*pkg.LocalPackage]struct{}{}
	for _, dt := range dm.Targets {
		t, err := lookUpTarget(dt)
		if err != nil {
			return nil, err
		}

		bspLpkg = t.Bsp()
		bspMap[bspLpkg] = struct{}{}
	}

	if dm.Bsp != "" {
		var err error
		bspLpkg, err = project.GetProject().ResolvePackage(
			basePkg.Repo(), dm.Bsp)
		if err != nil {
			return nil, util.FmtNewtError(
				"failed to resolve BSP package: %s", err.Error())
		}
		bspMap[bspLpkg] = struct{}{}
	}

	if len(bspMap) == 0 {
		return nil, util.FmtNewtError(
			"failed to determine BSP: no targets and no \"bsp\" field")
	}

	if len(bspMap) > 1 {
		return nil, util.FmtNewtError("multiple BSPs detected")
	}

	bsp, err := pkg.NewBspPackage(bspLpkg, nil)
	if err != nil {
		return nil, util.FmtNewtError(err.Error())
	}

	return bsp, nil
}

func (raw *MfgBuildRaw) ToPart(entryIdx int, baseAddress int) (Part, error) {
	data, err := ioutil.ReadFile(raw.Filename)
	if err != nil {
		return Part{}, util.ChildNewtError(err)
	}

	off, err := normalizeOffset(raw.Offset, len(data), raw.Area, baseAddress)
	if err != nil {
		return Part{}, err
	}

	return Part{
		Name:   fmt.Sprintf("raw-%d (%s)", entryIdx, raw.Filename),
		Offset: off,
		Data:   data,
	}, nil
}

func (mt *MfgBuildTarget) ToPart(baseAddress int) (Part, error) {
	data, err := ioutil.ReadFile(mt.BinPath)
	if err != nil {
		return Part{}, util.ChildNewtError(err)
	}

	off, err := normalizeOffset(mt.Offset, len(data), mt.Area, baseAddress)
	if err != nil {
		return Part{}, err
	}

	return Part{
		Name:   fmt.Sprintf("%s (%s)", mt.Area.Name, filepath.Base(mt.BinPath)),
		Offset: off,
		Data:   data,
	}, nil
}

func newMfgBuildTarget(dt DecodedTarget,
	fm flashmap.FlashMap) (MfgBuildTarget, error) {

	t, err := lookUpTarget(dt)
	if err != nil {
		return MfgBuildTarget{}, err
	}

	area, err := lookUpArea(fm, dt.Area)
	if err != nil {
		return MfgBuildTarget{}, err
	}

	mpath := builder.ManifestPath(dt.Name, builder.BUILD_NAME_APP, t.App().FullName())
	man, err := manifest.ReadManifest(mpath)
	if err != nil {
		return MfgBuildTarget{}, util.FmtNewtError("%s", err.Error())
	}

	isBoot := parse.ValueIsTrue(man.Syscfg["BOOT_LOADER"])

	binPath := targetSrcBinPath(t, isBoot)

	st, err := os.Stat(binPath)
	if err != nil {
		return MfgBuildTarget{}, errors.Wrapf(err,
			"failed to determine size of file \"%s\"", binPath)
	}

	return MfgBuildTarget{
		Target:        t,
		Area:          area,
		Offset:        dt.Offset,
		Size:          int(st.Size()),
		IsBoot:        isBoot,
		BinPath:       binPath,
		ExtraManifest: dt.ExtraManifest,
	}, nil
}

func newMfgBuildRaw(dr DecodedRaw, fm flashmap.FlashMap) (MfgBuildRaw, error) {
	checkFile := func(filename string) (string, int, error) {
		abs, err := filepath.Abs(filename)
		if err != nil {
			return "", 0, util.FmtNewtError(
				"failed to determine absolute path of file: path=%s", filename)
		}

		st, err := os.Stat(abs)
		if err != nil {
			return "", 0, errors.Wrapf(err,
				"failed to determine size of file \"%s\"", abs)
		}

		return abs, int(st.Size()), nil
	}

	filename, filesize, err := checkFile(dr.Filename)
	if err != nil {
		return MfgBuildRaw{}, err
	}

	var extraFiles []string
	for _, ef := range dr.ExtraFiles {
		ename, _, err := checkFile(ef)
		if err != nil {
			return MfgBuildRaw{}, err
		}
		extraFiles = append(extraFiles, ename)
	}

	area, err := lookUpArea(fm, dr.Area)
	if err != nil {
		return MfgBuildRaw{}, err
	}

	return MfgBuildRaw{
		Filename:      filename,
		Offset:        dr.Offset,
		Size:          filesize,
		Area:          area,
		ExtraFiles:    extraFiles,
		ExtraManifest: dr.ExtraManifest,
	}, nil
}

func newMfgBuildMeta(dm DecodedMeta,
	fm flashmap.FlashMap) (MfgBuildMeta, error) {

	area, ok := fm.Areas[dm.Area]
	if !ok {
		return MfgBuildMeta{}, util.FmtNewtError(
			"meta region specifies unrecognized flash area: \"%s\"", dm.Area)
	}

	var mmrs []MfgBuildMetaMmr
	for _, dmmr := range dm.Mmrs {
		area, err := lookUpArea(fm, dmmr.Area)
		if err != nil {
			return MfgBuildMeta{}, err
		}
		mmr := MfgBuildMetaMmr{
			Area: area,
		}
		mmrs = append(mmrs, mmr)
	}

	return MfgBuildMeta{
		Area:     area,
		Hash:     dm.Hash,
		FlashMap: dm.FlashMap,
		Mmrs:     mmrs,
	}, nil
}

func (mb *MfgBuilder) parts() ([]Part, error) {
	parts := []Part{}

	// Create parts from the raw entries.
	for i, raw := range mb.Raws {
		part, err := raw.ToPart(i, mb.BaseAddress)
		if err != nil {
			return nil, err
		}
		parts = append(parts, part)
	}

	// Create parts from the target entries.
	for _, t := range mb.Targets {
		part, err := t.ToPart(mb.BaseAddress)
		if err != nil {
			return nil, err
		}
		parts = append(parts, part)
	}

	// Sort by offset.
	return SortParts(parts), nil
}

func (mb *MfgBuilder) detectOverlaps() error {
	type overlap struct {
		p1 Part
		p2 Part
	}

	overlaps := []overlap{}

	parts, err := mb.parts()
	if err != nil {
		return err
	}

	for i, p1 := range parts[:len(parts)-1] {
		p1end := p1.Offset + len(p1.Data)
		for _, p2 := range parts[i+1:] {
			// Parts are sorted by offset, so only one comparison is
			// necessary to detect overlap.
			if p2.Offset < p1end {
				overlaps = append(overlaps, overlap{
					p1: p1,
					p2: p2,
				})
			}
		}
	}

	if len(overlaps) > 0 {
		str := "flash overlaps detected:"
		for _, overlap := range overlaps {

			p1end := overlap.p1.Offset + len(overlap.p1.Data)
			p2end := overlap.p2.Offset + len(overlap.p2.Data)
			str += fmt.Sprintf("\n    * [%s] (%d - %d) <=> [%s] (%d - %d)",
				overlap.p1.Name, overlap.p1.Offset, p1end,
				overlap.p2.Name, overlap.p2.Offset, p2end)
		}

		return util.NewNewtError(str)
	}

	return nil
}

// Determines which flash device the manufacturing image is intended for.  It
// is an error if the mfg definition specifies 0 or >1 devices.
func (mb *MfgBuilder) calcDevice() (int, error) {
	deviceMap := map[int]struct{}{}
	for _, t := range mb.Targets {
		deviceMap[t.Area.Device] = struct{}{}
	}
	for _, r := range mb.Raws {
		deviceMap[r.Area.Device] = struct{}{}
	}

	devices := make([]int, 0, len(deviceMap))
	for d, _ := range deviceMap {
		devices = append(devices, d)
	}
	sort.Ints(devices)

	if len(devices) == 0 {
		return 0, util.FmtNewtError(
			"manufacturing image definition does not indicate flash device")
	}

	if len(devices) > 1 {
		return 0, util.FmtNewtError(
			"multiple flash devices in use by single manufacturing image: %v",
			devices)
	}

	return devices[0], nil
}

func newMfgBuilder(basePkg *pkg.LocalPackage, dm DecodedMfg,
	ver image.ImageVersion) (MfgBuilder, error) {

	mb := MfgBuilder{
		BasePkg: basePkg,
	}

	bsp, err := calcBsp(dm, basePkg)
	if err != nil {
		return mb, err
	}
	mb.Bsp = bsp

	for _, dt := range dm.Targets {
		mbt, err := newMfgBuildTarget(dt, bsp.FlashMap)
		if err != nil {
			return mb, err
		}
		mb.Targets = append(mb.Targets, mbt)
	}

	for _, dr := range dm.Raws {
		mbr, err := newMfgBuildRaw(dr, bsp.FlashMap)
		if err != nil {
			return mb, err
		}
		mb.Raws = append(mb.Raws, mbr)
	}

	if dm.Meta != nil {
		meta, err := newMfgBuildMeta(*dm.Meta, mb.Bsp.FlashMap)
		if err != nil {
			return mb, err
		}
		mb.Meta = &meta
	}

	if _, err := mb.calcDevice(); err != nil {
		return mb, err
	}

	if err := mb.detectOverlaps(); err != nil {
		return mb, err
	}

	return mb, nil
}

// Creates a zeroed-out hash MMR TLV.  The hash's original value must be zero
// for the actual hash to be calculated later.  After the actual value is
// calculated, it replaces the zeros in the TLV.
func newZeroHashTlv() mfg.MetaTlv {
	return mfg.MetaTlv{
		Header: mfg.MetaTlvHeader{
			Type: mfg.META_TLV_TYPE_HASH,
			Size: mfg.META_TLV_HASH_SZ,
		},
		Data: make([]byte, mfg.META_HASH_SZ),
	}
}

// Creates a flash area MMR TLV.
func newFlashAreaTlv(area flash.FlashArea) (mfg.MetaTlv, error) {
	tlv := mfg.MetaTlv{
		Header: mfg.MetaTlvHeader{
			Type: mfg.META_TLV_TYPE_FLASH_AREA,
			Size: mfg.META_TLV_FLASH_AREA_SZ,
		},
	}

	body := mfg.MetaTlvBodyFlashArea{
		Area:   uint8(area.Id),
		Device: uint8(area.Device),
		Offset: uint32(area.Offset),
		Size:   uint32(area.Size),
	}

	b := &bytes.Buffer{}
	if err := binary.Write(b, binary.LittleEndian, body); err != nil {
		return tlv, util.ChildNewtError(err)
	}

	tlv.Data = b.Bytes()

	return tlv, nil
}

// Creates an MMR ref TLV.
func newMmrRefTlv(area flash.FlashArea) (mfg.MetaTlv, error) {
	tlv := mfg.MetaTlv{
		Header: mfg.MetaTlvHeader{
			Type: mfg.META_TLV_TYPE_MMR_REF,
			Size: mfg.META_TLV_MMR_REF_SZ,
		},
	}

	body := mfg.MetaTlvBodyMmrRef{
		Area: uint8(area.Id),
	}

	b := &bytes.Buffer{}
	if err := binary.Write(b, binary.LittleEndian, body); err != nil {
		return tlv, util.ChildNewtError(err)
	}

	tlv.Data = b.Bytes()

	return tlv, nil
}

// Builds a manufacturing meta region.
func (mb *MfgBuilder) buildMeta() (mfg.Meta, error) {
	meta := mfg.Meta{
		Footer: mfg.MetaFooter{
			Size:    0, // Filled in later.
			Version: mfg.META_VERSION,
			Pad8:    0xff,
			Magic:   mfg.META_MAGIC,
		},
	}

	// Hash TLV.
	if mb.Meta.Hash {
		meta.Tlvs = append(meta.Tlvs, newZeroHashTlv())
	}

	// Flash map TLVs.
	if mb.Meta.FlashMap {
		for _, area := range mb.Bsp.FlashMap.SortedAreas() {
			tlv, err := newFlashAreaTlv(area)
			if err != nil {
				return meta, err
			}

			meta.Tlvs = append(meta.Tlvs, tlv)
		}
	}

	// MMR ref TLVs.
	for _, mmr := range mb.Meta.Mmrs {
		tlv, err := newMmrRefTlv(mmr.Area)
		if err != nil {
			return meta, err
		}

		meta.Tlvs = append(meta.Tlvs, tlv)
	}

	// Fill in region size in footer now that we know the value.
	meta.Footer.Size = uint16(meta.Size())

	return meta, nil
}

// Builds a manufacturing image.
func (mb *MfgBuilder) Build() (mfg.Mfg, error) {
	parts, err := mb.parts()
	if err != nil {
		return mfg.Mfg{}, err
	}

	bin, err := PartsBytes(parts)
	if err != nil {
		return mfg.Mfg{}, err
	}

	var metaOff int
	var metap *mfg.Meta
	if mb.Meta != nil {
		meta, err := mb.buildMeta()
		if err != nil {
			return mfg.Mfg{}, err
		}
		metap = &meta
		metaOff = mb.Meta.Area.Offset + mb.Meta.Area.Size - meta.Size() - mb.BaseAddress
	}

	return mfg.Mfg{
		Bin:     bin,
		Meta:    metap,
		MetaOff: metaOff,
	}, nil
}
