// Copyright 2018 The LUCI Authors.
//
// Licensed 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 cipd

import (
	"context"
	"fmt"
	"sort"

	"go.chromium.org/luci/common/data/stringset"
	"go.chromium.org/luci/common/logging"

	"go.chromium.org/luci/cipd/common"
)

// Helper structs and implementation guts of EnsurePackages call.

// ActionKind defines what is being done to a particular package.
type ActionKind string

const (
	ActionRemove  ActionKind = "remove"  // package removal
	ActionRelink  ActionKind = "relink"  // restoration of broken symlinks
	ActionRepair  ActionKind = "repair"  // restoration of deleted files
	ActionInstall ActionKind = "install" // installation or upgrade
)

// Actions lists what the cipd.Client should do or did to ensure the state of
// some single subdirectory under the installation root.
//
// Is it part of a per-directory ActionMap returned by EnsurePackages.
type Actions struct {
	ToInstall common.PinSlice `json:"to_install,omitempty"` // pins to be installed
	ToUpdate  []UpdatedPin    `json:"to_update,omitempty"`  // pins to be replaced
	ToRemove  common.PinSlice `json:"to_remove,omitempty"`  // pins to be removed
	ToRepair  []BrokenPin     `json:"to_repair,omitempty"`  // pins to be repaired

	Errors []ActionError `json:"errors,omitempty"` // all individual errors
}

// Empty is true if there are no actions specified.
func (a *Actions) Empty() bool {
	return len(a.ToInstall) == 0 &&
		len(a.ToUpdate) == 0 &&
		len(a.ToRemove) == 0 &&
		len(a.ToRepair) == 0
}

// UpdatedPin specifies a pair of pins: old and new version of a package.
type UpdatedPin struct {
	From common.Pin `json:"from"`
	To   common.Pin `json:"to"`
}

// BrokenPin specifies a pin that should be repaired and how.
type BrokenPin struct {
	Pin        common.Pin `json:"pin"`
	RepairPlan RepairPlan `json:"repair_plan"`
}

// RepairPlan describes what should be redeployed to fix a broken pin.
type RepairPlan struct {
	// NeedsReinstall is true if the package is broken to the point it is simpler
	// to completely reinstall it.
	//
	// ReinstallReason contains explanation why the reinstall is needed.
	//
	// If NeedsReinstall is false, then the package may be repaired just by
	// extracting a bunch of files, specified in ToRedeploy list.
	NeedsReinstall bool `json:"needs_reinstall,omitempty"`

	// ReinstallReason is a human-readable reason of why the package should be
	// completely reinstalled rather than selectively repaired.
	ReinstallReason string `json:"reinstall_reason,omitempty"`

	// ToRedeploy is a list of slash-separated file names (as they are specified
	// inside the package file) that needs to be reextracted from the original
	// package and relinked into the site root in order to repair the deployment.
	//
	// If this list is not empty, it means we'll need an original package file
	// to repair the deployment.
	//
	// Set only if NeedsReinstall is false.
	ToRedeploy []string `json:"to_redeploy,omitempty"`

	// ToRelink is a list of slash-separated file names (as they are specified
	// inside the package file) that needs to be relinked into the site root in
	// order to repair the deployment.
	//
	// They are already present in the .cipd/* guts, so there's no need to fetch
	// the original package file to get them.
	//
	// Set only if NeedsReinstall is false.
	ToRelink []string `json:"to_relink,omitempty"`
}

// NumBrokenFiles returns number of files that will be repaired.
func (p *RepairPlan) NumBrokenFiles() int {
	return len(p.ToRedeploy) + len(p.ToRelink)
}

// ActionError holds an error that happened when working on the pin.
type ActionError struct {
	Action ActionKind `json:"action"`
	Pin    common.Pin `json:"pin"`
	Error  JSONError  `json:"error,omitempty"`
}

// ActionMap is a map of subdir to the Actions which will occur within it.
type ActionMap map[string]*Actions

// Empty is true if ActionMap is empty.
func (am ActionMap) Empty() bool {
	for _, a := range am {
		if !a.Empty() {
			return false
		}
	}
	return true
}

// loopOrdered loops over the ActionMap in sorted order (by subdir).
func (am ActionMap) loopOrdered(cb func(subdir string, actions *Actions)) {
	subdirs := make(sort.StringSlice, 0, len(am))
	for subdir := range am {
		subdirs = append(subdirs, subdir)
	}
	subdirs.Sort()
	for _, subdir := range subdirs {
		cb(subdir, am[subdir])
	}
}

// Log prints the pending action to the logger installed in ctx.
//
// If verbose is true, prints filenames of files that need a repair.
func (am ActionMap) Log(ctx context.Context, verbose bool) {
	keys := make([]string, 0, len(am))
	for key := range am {
		keys = append(keys, key)
	}
	sort.Strings(keys)

	for _, subdir := range keys {
		actions := am[subdir]

		if subdir == "" {
			logging.Infof(ctx, "In root:")
		} else {
			logging.Infof(ctx, "In subdir %q:", subdir)
		}

		if len(actions.ToInstall) != 0 {
			logging.Infof(ctx, "  to install:")
			for _, pin := range actions.ToInstall {
				logging.Infof(ctx, "    %s", pin)
			}
		}
		if len(actions.ToUpdate) != 0 {
			logging.Infof(ctx, "  to update:")
			for _, pair := range actions.ToUpdate {
				logging.Infof(ctx, "    %s (%s -> %s)",
					pair.From.PackageName, pair.From.InstanceID, pair.To.InstanceID)
			}
		}
		if len(actions.ToRemove) != 0 {
			logging.Infof(ctx, "  to remove:")
			for _, pin := range actions.ToRemove {
				logging.Infof(ctx, "    %s", pin)
			}
		}
		if len(actions.ToRepair) != 0 {
			logging.Infof(ctx, "  to repair:")
			for _, broken := range actions.ToRepair {
				more := broken.RepairPlan.ReinstallReason
				if more == "" {
					more = fmt.Sprintf("%d file(s) to repair", broken.RepairPlan.NumBrokenFiles())
				}
				logging.Infof(ctx, "    %s (%s)", broken.Pin, more)
				if verbose && len(broken.RepairPlan.ToRedeploy) != 0 {
					logging.Infof(ctx, "      to redeploy:")
					for _, f := range broken.RepairPlan.ToRedeploy {
						logging.Infof(ctx, "        %s", f)
					}
				}
				if verbose && len(broken.RepairPlan.ToRelink) != 0 {
					logging.Infof(ctx, "      to relink:")
					for _, f := range broken.RepairPlan.ToRelink {
						logging.Infof(ctx, "        %s", f)
					}
				}
			}
		}
	}
}

// perPinActions is a "rotated" version of ActionMap where actions are grouped
// by (operation, pin) pairs essentially, not by the subdir they touch.
type perPinActions struct {
	maintenance []pinAction     // don't need package data: removals and relinks
	updates     []updateActions // need package data: installs and repairs
}

// pinAction is an action done to some pin in some subdir.
type pinAction struct {
	action     ActionKind
	pin        common.Pin
	subdir     string
	repairPlan RepairPlan // populated for relinks and repairs only
}

// updateActions is a list of actions that need the package data of this
// specific pin. These are installations (including updates) and repairs.
type updateActions struct {
	pin     common.Pin
	updates []pinAction
}

// perPinActions splits the action map into per-pin action lists.
func (am ActionMap) perPinActions() perPinActions {
	var maintenance []pinAction

	addMaintenanceAction := func(a ActionKind, subdir string, pin common.Pin, plan RepairPlan) {
		maintenance = append(maintenance, pinAction{
			action:     a,
			pin:        pin,
			subdir:     subdir,
			repairPlan: plan,
		})
	}

	var updates []updateActions
	seen := map[common.Pin]int{} // pin => index in `updates`

	addUpdateAction := func(a ActionKind, subdir string, pin common.Pin, plan RepairPlan) {
		idx, ok := seen[pin]
		if !ok {
			updates = append(updates, updateActions{pin: pin})
			idx = len(updates) - 1
			seen[pin] = idx
		}
		updates[idx].updates = append(updates[idx].updates, pinAction{
			action:     a,
			pin:        pin,
			subdir:     subdir,
			repairPlan: plan,
		})
	}

	am.loopOrdered(func(subdir string, actions *Actions) {
		for _, pin := range actions.ToRemove {
			addMaintenanceAction(ActionRemove, subdir, pin, RepairPlan{})
		}
		for _, pin := range actions.ToInstall {
			addUpdateAction(ActionInstall, subdir, pin, RepairPlan{})
		}
		for _, pair := range actions.ToUpdate {
			addUpdateAction(ActionInstall, subdir, pair.To, RepairPlan{})
		}
		for _, broken := range actions.ToRepair {
			if broken.RepairPlan.NeedsReinstall {
				// Need the full reinstall, requires the package data.
				addUpdateAction(ActionInstall, subdir, broken.Pin, broken.RepairPlan)
			} else if len(broken.RepairPlan.ToRedeploy) != 0 {
				// Need to redeploy some files, requires the package data.
				addUpdateAction(ActionRepair, subdir, broken.Pin, broken.RepairPlan)
			} else {
				// Need to symlink existing files, no need to fetch the package data.
				addMaintenanceAction(ActionRelink, subdir, broken.Pin, broken.RepairPlan)
			}
		}
	})

	return perPinActions{maintenance, updates}
}

// repairCB is called for each installed pin to decide whether it should be
// repaired and how.
type repairCB func(subdir string, pin common.Pin) *RepairPlan

// buildActionPlan is used by EnsurePackages to figure out what to install,
// remove, update or repair.
//
// The given 'needsRepair' callback is called for each installed pin to decide
// whether it should be repaired and how.
func buildActionPlan(desired, existing common.PinSliceBySubdir, needsRepair repairCB) (aMap ActionMap) {
	desiredSubdirs := stringset.New(len(desired))
	for desiredSubdir := range desired {
		desiredSubdirs.Add(desiredSubdir)
	}

	existingSubdirs := stringset.New(len(existing))
	for existingSubdir := range existing {
		existingSubdirs.Add(existingSubdir)
	}

	aMap = ActionMap{}

	// all newly added subdirs
	desiredSubdirs.Difference(existingSubdirs).Iter(func(subdir string) bool {
		if want := desired[subdir]; len(want) > 0 {
			aMap[subdir] = &Actions{ToInstall: want}
		}
		return true
	})

	// all removed subdirs
	existingSubdirs.Difference(desiredSubdirs).Iter(func(subdir string) bool {
		if have := existing[subdir]; len(have) > 0 {
			aMap[subdir] = &Actions{ToRemove: have}
		}
		return true
	})

	// all common subdirs
	desiredSubdirs.Intersect(existingSubdirs).Iter(func(subdir string) bool {
		a := Actions{}

		// Figure out what needs to be installed, updated or repaired.
		haveMap := existing[subdir].ToMap()
		for _, want := range desired[subdir] {
			if haveID, exists := haveMap[want.PackageName]; !exists {
				a.ToInstall = append(a.ToInstall, want)
			} else if haveID != want.InstanceID {
				a.ToUpdate = append(a.ToUpdate, UpdatedPin{
					From: common.Pin{PackageName: want.PackageName, InstanceID: haveID},
					To:   want,
				})
			} else if repairPlan := needsRepair(subdir, want); repairPlan != nil {
				a.ToRepair = append(a.ToRepair, BrokenPin{
					Pin:        want,
					RepairPlan: *repairPlan,
				})
			}
		}

		// Figure out what needs to be removed.
		wantMap := desired[subdir].ToMap()
		for _, have := range existing[subdir] {
			if wantMap[have.PackageName] == "" {
				a.ToRemove = append(a.ToRemove, have)
			}
		}

		if !a.Empty() {
			aMap[subdir] = &a
		}
		return true
	})

	if len(aMap) == 0 {
		return nil
	}
	return
}
