package projectmetadata

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/golang/protobuf/proto"
	xnetcontext "golang.org/x/net/context"
	"google.golang.org/grpc/codes"

	pb "code.justin.tv/dta/rockpaperscissors/proto"
)

var (
	// ErrTeamNameNotSet is returned when team_name isn't given when
	// requesting team details.
	ErrTeamNameNotSet = errf(codes.InvalidArgument, "No team_name was given.")
	// ErrTeamNotFound if returned when the given team name isn't in the datastore.
	ErrTeamNotFound = errf(codes.NotFound, "Team not found.")
)

// ListTeams returns a list of team names and projects for each team.
func (s *Server) ListTeams(ctx xnetcontext.Context, req *pb.ListTeamsRequest) (*pb.ListTeamsResponse, error) {
	records, err := s.listProjectRecords(req.IncludeArchived, nil, nil)
	if err != nil {
		return nil, err
	}

	teamsMap := make(map[string][]*pb.ProjectMetadata)

	// Fill in the static data
	for _, teams := range StaticHeirarchy {
		for _, teamName := range teams {
			teamsMap[teamName] = make([]*pb.ProjectMetadata, 0)
		}
	}

	for _, record := range records {
		// TODO: check project_id and project_name attributes exist for each item?
		if len(record.TeamName) == 0 {
			continue
		}
		teamsMap[record.TeamName] = append(teamsMap[record.TeamName], &pb.ProjectMetadata{
			ProjectId:   proto.String(record.ProjectID),
			ProjectName: proto.String(record.ProjectName),
			TeamName:    proto.String(record.TeamName),
			Archived:    proto.Bool(record.Archived),
		})
	}

	listResponse := &pb.ListTeamsResponse{}
	for teamName, projects := range teamsMap {
		entry := &pb.ListTeamsResponse_TeamEntry{
			TeamName: teamName,
			Projects: projects,
		}
		listResponse.Teams = append(listResponse.Teams, entry)
	}

	return listResponse, nil
}

// GetTeam returns some details about the team including what projects are part of it.
func (s *Server) GetTeam(ctx xnetcontext.Context, req *pb.GetTeamRequest) (*pb.GetTeamResponse, error) {
	if len(req.TeamName) == 0 {
		return nil, ErrTeamNameNotSet
	}

	teamName := req.TeamName
	records, err := s.listProjectRecords(true, &teamName, nil)
	if err != nil {
		return nil, err
	}

	if len(records) == 0 {
		// No projects have that team, check static data before we say not found.
		found := false
	Outer:
		for _, orgSlice := range StaticHeirarchy {
			for _, staticTeamName := range orgSlice {
				if staticTeamName == teamName {
					found = true
					break Outer
				}
			}
		}
		if !found {
			return nil, ErrTeamNotFound
		}
	}

	response := &pb.GetTeamResponse{
		TeamName: teamName,
		Projects: make([]*pb.ProjectMetadata, len(records)),
	}
	for i, record := range records {
		response.Projects[i] = &pb.ProjectMetadata{
			ProjectId:   aws.String(record.ProjectID),
			ProjectName: aws.String(record.ProjectName),
			TeamName:    aws.String(record.TeamName),
			Archived:    aws.Bool(record.Archived),
		}
	}

	return response, nil
}
