// Copyright 2019 Google LLC
//
// 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
//
//     https://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 com.google.sps.servlets;

import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.sps.classes.KeywordCampaign;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.SortDirection;
import java.io.IOException;
import java.io.PrintWriter;
import com.google.gson.Gson;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;

// runs all the pending DSA campaigns for the logged-in user through the black box and updates estimation results
@WebServlet("/black-box")
public class BlackBoxServlet extends HttpServlet {
    
    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {	
        UserService userService = UserServiceFactory.getUserService();

        if (userService.isUserLoggedIn()) {
            String userId = userService.getCurrentUser().getUserId();

            // get the pending DSA campaigns associated with the logged-in user from datastore
            DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
            Query query = new Query("DSACampaign").setFilter(new Query.FilterPredicate("userId", Query.FilterOperator.EQUAL, userId))
                .setFilter(new Query.FilterPredicate("campaignStatus", Query.FilterOperator.EQUAL, "pending"));
            PreparedQuery results = datastore.prepare(query);
            
            for (Entity DSACampaignEntity : results.asIterable()) {
                // run the DSA campaign through the black box
                blackbox(DSACampaignEntity);
            }

            response.sendRedirect("/Home/home.html");
        } else {
            response.sendRedirect("/index.html");
        }
    }

    /*
     * Runs the DSA campaign and obtains estimation results.
     * Updates the DSA campaign entity with the estimation results and changes the campaign status from pending to complete.
     * Implementation explanations are in the design doc.
     */
    public static void blackbox(Entity DSACampaignEntity) {
        // retrieve the DSA campaign's corresponding keyword campaign from datastore
        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
        Query query = new Query("keywordCampaign").setFilter(new Query.FilterPredicate("keywordCampaignId", Query.FilterOperator.EQUAL, (String) DSACampaignEntity.getProperty("keywordCampaignId")));
    	Entity keywordCampaignEntity = datastore.prepare(query).asSingleEntity();

        // calculate the estimation results
        double websiteFactor = getWebsiteFactor(keywordCampaignEntity, DSACampaignEntity);
        int impressions = getImpressionsEstimate(keywordCampaignEntity, DSACampaignEntity, websiteFactor);
        int clicks = getClicksEstimate(keywordCampaignEntity, DSACampaignEntity, websiteFactor);
        double cost = clicks*((double) DSACampaignEntity.getProperty("manualCPC"));

        // update the DSA campaign entity in datastore with the estimation results
        DSACampaignEntity.setProperty("impressions", impressions);
        DSACampaignEntity.setProperty("clicks", clicks);
        DSACampaignEntity.setProperty("cost", cost);
        DSACampaignEntity.setProperty("campaignStatus", "complete");
        datastore.put(DSACampaignEntity);

        // TODO: SQR
    }
}
@@ -4329,10 +4329,822 @@
 QR%0A    %7D
+%0A%0A     public static int getImpressionsEstimate(Entity keywordCampaignEntity, Entity DSACampaignEntity, double websiteFactor) %7B%0A        double manualCPCFactor = getManualCPCFactor(keywordCampaignEntity, DSACampaignEntity);%0A        double locationsFactor = getLocationsFactor(DSACampaignEntity);%0A        double upliftFactor = .25*manualCPCFactor + .25*locationsFactor + .50*websiteFactor;%0A%0A        return (int) Math.round(upliftFactor*((int) keywordCampaignEntity.getProperty(%22impressions%22)));%0A    %7D%0A%0A    public static double getManualCPCFactor(Entity keywordCampaignEntity, Entity DSACampaignEntity) %7B%0A        double ratio = ((double) DSACampaignEntity.getProperty(%22manualCPC%22))/((double) keywordCampaignEntity.getProperty(%22manualCPC%22));%0A        ratio = Math.sqrt(ratio);%0A        return Math.min(ratio, 3);%0A    %7D
 %0A%7D

Add more helper functions.