// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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 breakpoints handles breakpoint requests we get from the user through
// the Debuglet Controller, and manages corresponding breakpoints set in the code.
package breakpoints

import (
	"log"
	"sync"

	"golang.org/x/debug"
	cd "google.golang.org/api/clouddebugger/v2"
)

// BreakpointStore stores the set of breakpoints for a program.
type BreakpointStore struct {
	mu sync.Mutex
	// prog is the program being debugged.
	prog debug.Program
	// idToBreakpoint is a map from breakpoint identifier to *cd.Breakpoint.  The
	// map value is nil if the breakpoint is inactive.  A breakpoint is active if:
	// - We received it from the Debuglet Controller, and it was active at the time;
	// - We were able to set code breakpoints for it;
	// - We have not reached any of those code breakpoints while satisfying the
	//   breakpoint's conditions, or the breakpoint has action LOG; and
	// - The Debuglet Controller hasn't informed us the breakpoint has become inactive.
	idToBreakpoint map[string]*cd.Breakpoint
	// pcToBps and bpToPCs store the many-to-many relationship between breakpoints we
	// received from the Debuglet Controller and the code breakpoints we set for them.
	pcToBps map[uint64][]*cd.Breakpoint
	bpToPCs map[*cd.Breakpoint][]uint64
	// errors contains any breakpoints which couldn't be set because they caused an
	// error.  These are retrieved with ErrorBreakpoints, and the caller is
	// expected to handle sending updates for them.
	errors []*cd.Breakpoint
}

// NewBreakpointStore returns a BreakpointStore for the given program.
func NewBreakpointStore(prog debug.Program) *BreakpointStore {
	return &BreakpointStore{
		idToBreakpoint: make(map[string]*cd.Breakpoint),
		pcToBps:        make(map[uint64][]*cd.Breakpoint),
		bpToPCs:        make(map[*cd.Breakpoint][]uint64),
		prog:           prog,
	}
}

// ProcessBreakpointList applies updates received from the Debuglet Controller through a List call.
func (bs *BreakpointStore) ProcessBreakpointList(bps []*cd.Breakpoint) {
	bs.mu.Lock()
	defer bs.mu.Unlock()
	for _, bp := range bps {
		if storedBp, ok := bs.idToBreakpoint[bp.Id]; ok {
			if storedBp != nil && bp.IsFinalState {
				// IsFinalState indicates that the breakpoint has been made inactive.
				bs.removeBreakpointLocked(storedBp)
			}
		} else {
			if bp.IsFinalState {
				// The controller is notifying us that the breakpoint is no longer active,
				// but we didn't know about it anyway.
				continue
			}
			if bp.Action != "" && bp.Action != "CAPTURE" && bp.Action != "LOG" {
				bp.IsFinalState = true
				bp.Status = &cd.StatusMessage{
					Description: &cd.FormatMessage{Format: "Action is not supported"},
					IsError:     true,
				}
				bs.errors = append(bs.errors, bp)
				// Note in idToBreakpoint that we've already seen this breakpoint, so that we
				// don't try to report it as an error multiple times.
				bs.idToBreakpoint[bp.Id] = nil
				continue
			}
			pcs, err := bs.prog.BreakpointAtLine(bp.Location.Path, uint64(bp.Location.Line))
			if err != nil {
				log.Printf("error setting breakpoint at %s:%d: %v", bp.Location.Path, bp.Location.Line, err)
			}
			if len(pcs) == 0 {
				// We can't find a PC for this breakpoint's source line, so don't make it active.
				// TODO: we could snap the line to a location where we can break, or report an error to the user.
				bs.idToBreakpoint[bp.Id] = nil
			} else {
				bs.idToBreakpoint[bp.Id] = bp
				for _, pc := range pcs {
					bs.pcToBps[pc] = append(bs.pcToBps[pc], bp)
				}
				bs.bpToPCs[bp] = pcs
			}
		}
	}
}

// ErrorBreakpoints returns a slice of Breakpoints that caused errors when the
// BreakpointStore tried to process them, and resets the list of such
// breakpoints.
// The caller is expected to send updates to the server to indicate the errors.
func (bs *BreakpointStore) ErrorBreakpoints() []*cd.Breakpoint {
	bs.mu.Lock()
	defer bs.mu.Unlock()
	bps := bs.errors
	bs.errors = nil
	return bps
}

// BreakpointsAtPC returns all the breakpoints for which we set a code
// breakpoint at the given address.
func (bs *BreakpointStore) BreakpointsAtPC(pc uint64) []*cd.Breakpoint {
	bs.mu.Lock()
	defer bs.mu.Unlock()
	return bs.pcToBps[pc]
}

// RemoveBreakpoint makes the given breakpoint inactive.
// This is called when either the debugged program hits the breakpoint, or the Debuglet
// Controller informs us that the breakpoint is now inactive.
func (bs *BreakpointStore) RemoveBreakpoint(bp *cd.Breakpoint) {
	bs.mu.Lock()
	bs.removeBreakpointLocked(bp)
	bs.mu.Unlock()
}

func (bs *BreakpointStore) removeBreakpointLocked(bp *cd.Breakpoint) {
	// Set the ID's corresponding breakpoint to nil, so that we won't activate it
	// if we see it again.
	// TODO: we could delete it after a few seconds.
	bs.idToBreakpoint[bp.Id] = nil

	// Delete bp from the list of cd breakpoints at each of its corresponding
	// code breakpoint locations, and delete any code breakpoints which no longer
	// have a corresponding cd breakpoint.
	var codeBreakpointsToDelete []uint64
	for _, pc := range bs.bpToPCs[bp] {
		bps := remove(bs.pcToBps[pc], bp)
		if len(bps) == 0 {
			// bp was the last breakpoint set at this PC, so delete the code breakpoint.
			codeBreakpointsToDelete = append(codeBreakpointsToDelete, pc)
			delete(bs.pcToBps, pc)
		} else {
			bs.pcToBps[pc] = bps
		}
	}
	if len(codeBreakpointsToDelete) > 0 {
		bs.prog.DeleteBreakpoints(codeBreakpointsToDelete)
	}
	delete(bs.bpToPCs, bp)
}

// remove updates rs by removing r, then returns rs.
// The mutex in the BreakpointStore which contains rs should be held.
func remove(rs []*cd.Breakpoint, r *cd.Breakpoint) []*cd.Breakpoint {
	for i := range rs {
		if rs[i] == r {
			rs[i] = rs[len(rs)-1]
			rs = rs[0 : len(rs)-1]
			return rs
		}
	}
	// We shouldn't reach here.
	return rs
}
