package com.aemreunal.service;

import java.util.ArrayList;
import java.util.List;
import javax.validation.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.aemreunal.config.GlobalSettings;
import com.aemreunal.domain.Beacon;
import com.aemreunal.domain.Project;
import com.aemreunal.exception.beacon.BeaconNotFoundException;
import com.aemreunal.exception.project.ProjectNotFoundException;
import com.aemreunal.repository.beacon.BeaconRepo;
import com.aemreunal.repository.beacon.BeaconSpecs;

/*
 **************************
 * Copyright (c) 2014     *
 *                        *
 * This code belongs to:  *
 *                        *
 * Ahmet Emre Ünal        *
 * S001974                *
 *                        *
 * aemreunal@gmail.com    *
 * emre.unal@ozu.edu.tr   *
 *                        *
 * aemreunal.com          *
 **************************
 */

@Transactional
@Service
public class BeaconService {
    @Autowired
    private ProjectService projectService;

    @Autowired
    private BeaconRepo beaconRepo;

    /**
     * Saves/updates the given beacon
     *
     * @param beacon
     *     The beacon to save/update
     *
     * @return The saved/updated beacon
     */
    public Beacon save(String username, Long projectId, Beacon beacon) throws ConstraintViolationException {
        if (GlobalSettings.DEBUGGING) {
            System.out.println("Saving beacon with ID = \'" + beacon.getBeaconId() + "\'");
        }
        // Even though the 'project' variable is only used inside the if-clause,
        // the Project is found no matter what to ensure it exists and legitimate.
        Project project = projectService.findProjectById(username, projectId);
        if(beacon.getProject() == null) {
            // This means it hasn't been saved yet
            beacon.setProject(project);
        }
        return beaconRepo.save(beacon);
    }

    /**
     * Finds beacons conforming to given specifications
     *
     * @param projectId
     *     The project ID constraint
     * @param uuid
     *     The UUID field constraint
     * @param major
     *     The Major field constraint
     * @param minor
     *     The Minor field constraint
     *
     * @return The list of beacons conforming to given constraints
     */
    public List<Beacon> findBeaconsBySpecs(String username, Long projectId, String uuid, String major, String minor) {
        if (GlobalSettings.DEBUGGING) {
            System.out.println("Finding beacons with UUID = \'" + uuid + "\' major = \'" + major + "\' minor = \'" + minor + "\'");
        }
        Project project = projectService.findProjectById(username, projectId);
        List<Beacon> beacons = beaconRepo.findAll(BeaconSpecs.beaconWithSpecification(project.getProjectId(), uuid, major, minor));
        if (beacons.size() == 0) {
            throw new BeaconNotFoundException();
        }
        return beacons;
    }

    /**
     * Finds the {@link com.aemreunal.domain.Beacon beacon} with the specified projectId
     * in a {@link com.aemreunal.domain.Project project}.
     *
     * @param username
     *     The username of the {@link com.aemreunal.domain.User owner} of the project
     * @param projectId
     *     The ID of the project
     * @param beaconId
     *     The ID of the beacon to find
     *
     * @return The beacon
     *
     * @throws com.aemreunal.exception.beacon.BeaconNotFoundException
     *     If the specified beacon does not exist.
     * @throws com.aemreunal.exception.project.ProjectNotFoundException
     *     If the specified project does not exist.
     */
    public Beacon getBeacon(String username, Long projectId, Long beaconId) throws BeaconNotFoundException, ProjectNotFoundException {
        if (GlobalSettings.DEBUGGING) {
            System.out.println("Finding beacon with ID = \'" + beaconId + "\' in project = \'" + projectId + "\'");
        }
        Project project = projectService.findProjectById(username, projectId);
        Beacon beacon = beaconRepo.findByBeaconIdAndProject(beaconId, project);
        if (beacon == null) {
            throw new BeaconNotFoundException(beaconId);
        }
        return beacon;
    }

    /**
     * Returns the list of {@link com.aemreunal.domain.Beacon beacons} that belong to a
     * {@link com.aemreunal.domain.Project project}.
     *
     * @param username
     *     The username of the {@link com.aemreunal.domain.User owner} of the project
     * @param projectId
     *     The ID of the project
     *
     * @return The list of beacons that belong to a project. Returns an empty list if the
     * project has no beacons
     */
    public List<Beacon> getBeaconsOfProject(String username, Long projectId) {
        Project project = projectService.findProjectById(username, projectId);
        List<Beacon> beacons = new ArrayList<Beacon>();
        for (Beacon beacon : project.getBeacons()) {
            beacons.add(beacon);
        }
        return beacons;
    }

    public Beacon delete(String username, Long projectId, Long beaconId) {
        if (GlobalSettings.DEBUGGING) {
            System.out.println("Deleting beacon with ID = \'" + beaconId + "\'");
        }

        Beacon beacon = this.getBeacon(username, projectId, beaconId);
        beaconRepo.delete(beaconId);
        return beacon;
    }
}

@@ -193,16 +193,89 @@
 owired;%0A
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;%0A
 import o
@@ -313,16 +313,16 @@
 ervice;%0A
-
 import o
@@ -1262,16 +1262,83 @@
 nRepo;%0A%0A
+    @Autowired%0A    private BCryptPasswordEncoder passwordEncoder;%0A%0A
     /**%0A
@@ -1999,16 +1999,17 @@
       if
+ 
 (beacon.
@@ -2629,51 +2629,223 @@
 ame,
- Long projectId, String uuid, String major,
+%0A                                           Long projectId,%0A                                           String uuid,%0A                                           String major,%0A                                          
  Str
@@ -3336,32 +3336,32 @@
 on();%0A        %7D%0A
-
         return b
@@ -3367,32 +3367,676 @@
 beacons;%0A    %7D%0A%0A
+    public Beacon queryForBeacon(String uuid,%0A                                 String major,%0A                                 String minor,%0A                                 String projectSecret)%0A    throws BeaconNotFoundException %7B%0A        Beacon beacon = (Beacon) beaconRepo.findOne(BeaconSpecs.beaconWithSpecification(null, uuid, major, minor));%0A        if (beacon == null %7C%7C !(passwordEncoder.matches(projectSecret, beacon.getProject().getProjectSecret()))) %7B%0A            // Throw not found exception if it really doesn't exist or the secret is wrong.%0A            throw new BeaconNotFoundException();%0A        %7D%0A        return beacon;%0A    %7D%0A%0A
     /**%0A     * F

Add beacon query method