package samuelb.capripol.Controllers;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.view.RedirectView;
import samuelb.capripol.*;
import samuelb.capripol.Repositories.*;
import samuelb.capripol.Services.GroupService;
import samuelb.capripol.Services.UserDetailsServiceImpl;

import javax.servlet.http.HttpServletResponse;
import java.security.Principal;
import java.util.*;

/*
Controller for Main Menu, only real function is to handle the datatable data.
Claim controller is used for handling any actions on the datatable itself
 */
@Controller
public class MainMenuController {

    @Autowired
    private GroupRepository groupRepository;

    @Autowired
    private GroupService groupService;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private FocusRepository focusRepository;

    @Autowired
    private FrameworkRepository frameworkRepository;

    @Autowired
    private SightingRepository sightingRepository;

    private static Logger logger = LoggerFactory.getLogger(UserDetailsServiceImpl.class);


    @GetMapping(value ={"/", "/MainMenu"})
    public String index(Model model, Principal principal){
        return "MainMenu";
    }

    //Data to populate the DataTable
    @GetMapping(value = "/MainMenuData", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public List<Object> mainMenuData(@RequestParam (required = false) String allFoci, Model model, Principal principal){
        User user = userRepository.findByUserName(principal.getName());
        List<Object> data = new LinkedList<>();
        List<Set<String>> sortDetails = new ArrayList<>();
        //used for sorting the table, don't need them to be focus specific
        Set<String> allGroups = new HashSet<>();
        Set<String> allFrameworks = new HashSet<>();
        Set<String> allCategories = new HashSet<>();
        if(user != null){
            List<Focus> foci;
            if(allFoci != null && allFoci.equals("yes")){ //if show all foci is selected
                foci = focusRepository.findAll();
            }else{
                foci = focusRepository.findByUserID(user.getUserId());
            }
            for(Focus focus: foci){ //collecting data for each focus the user has access to
                int self = sightingRepository.findSelfClaimsForFocus(user.getUserId(), focus.getFocusId()).size();
                int peer = sightingRepository.findClaimsForFocusByRelationShip("peer", user.getUserId(), focus.getFocusId()).size();
                int peerReceived = sightingRepository.findClaimsForFocusByRelationShipReceived("peer", user.getUserId(), focus.getFocusId()).size();
                int other = sightingRepository.findClaimsForFocusByRelationShip("other", user.getUserId(), focus.getFocusId()).size();
                int otherReceived = sightingRepository.findClaimsForFocusByRelationShipReceived("otherReceived", user.getUserId(), focus.getFocusId()).size();
                int total = peer+other;
                int totalReceived = peerReceived+otherReceived+self;
                List<String> groups = new ArrayList<>();
                List<String> frameworks = new ArrayList<>();
                List<String> categories = new ArrayList<>();
                for(Framework framework: focus.getFrameworks()){ //this foci's frameworks
                    frameworks.add(framework.getFrameworkName());
                    allFrameworks.add(framework.getFrameworkName());
                    for(Group group: framework.getGroups()){ //this foci's frameworks' groups
                        groups.add(group.getGroupName());
                        allGroups.add(group.getGroupName());
                    }
                }
                if (!focus.getFocusCategory().equals("")) {
                    categories.add(focus.getFocusCategory());
                    allCategories.add(focus.getFocusCategory());
                }
                //this represents one row in the datatable
                String[] fociDetails = {focus.getFocusName(), userRepository.getUserRating(user.getRating(focus), user.getUserId(),
                        focus.getFocusId()).toString(), String.valueOf(self), String.valueOf(peerReceived), String.valueOf(otherReceived),
                        String.valueOf(totalReceived), String.valueOf(peer), String.valueOf(other), String.valueOf(total)};
                List test = Arrays.asList(fociDetails);
                test = new ArrayList(test);
                test.add(groups);
                test.add(frameworks);
                test.add(categories);
                data.add(test); //adds the foci details plus its associated groups, frameworks and categories
            }
            //Gets size of members to check if Give Claim should be enabled
            Set<String> memberCount = new HashSet<>(); //Using a set because it just easier to throw in w/ sort details
            for(Group group: user.getGroups()){
                Set<User> groupMembers = group.getGroupMembers();
                groupMembers.remove(user);
                memberCount.add(String.valueOf(groupMembers.size()));
            }
            sortDetails.add(memberCount);
        }
        sortDetails.add(allGroups);
        sortDetails.add(allFrameworks);
        sortDetails.add(allCategories);
        data.add(sortDetails); //adding the sort information on the end of the data to be popped off later
        return data;
    }
}
