/*
** Module   : HttpResponseCookie.java
** Abstract : A test for a HTTP response cookie.
**
** Copyright (c) 2024, Golden Code Development Corporation.
**
** -#- -I- --Date-- ---------------------------------------Description----------------------------------------
** 001 CA  20240724 Created initial version.
*/

/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Affero General Public License for more details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


package com.goldencode.harness.test;

import java.net.HttpCookie;
import java.util.List;

import org.apache.http.*;
import org.apache.http.cookie.*;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.client.*;

import com.goldencode.harness.*;

/**
 * A test applied to a response cookie.
 */
public class HttpResponseCookie
extends Report
implements WebResponseTestable
{
   /** The cookie name. */
   private String name;
   
   /** The expected cookie value. */
   private String value;
   
   /** The variable to save the path's value. */
   private String variable;

   /** The resource pool to store the variable. */
   private ResourcePool pool;

   /**
    * Configure a new cookie test.
    * 
    * @param    name
    *           The cookie name.
    * @param    value
    *           The expected cookie value (can be <code>null</code>).
    * @param    variable
    *           The variable name.
    * @param    pool
    *           The resource pool, to save the variable.
    */
   public HttpResponseCookie(String name, String value, String variable, ResourcePool pool)
   {
      this.name = name;
      this.value = value;
      this.variable = variable;
      this.pool = pool;
   }

   /**
    * Execute the test.  Exactly one {@link #name cookie} must exist, and its value must match exactly with the
    * {@link #value expected value} (if it was set).
    * 
    * @param    response
    *           The HTTP response.
    */
   @Override
   public void execute(HttpResponse response)
   {
      BasicCookieStore cookies = parseCookies(response.getHeaders("Set-cookie"));

      Cookie found = null;
      for (Cookie c : cookies.getCookies())
      {
         if (c.getName().equals(name))
         {
            if (found != null)
            {
               found = null;
               break;
            }
            
            found = c;
         }
      }
      
      if (found == null)
      {
         setStatus(Status.FAILED, "Exactly one cookie '" + name + "' must exist!");
         return;
      }
      
      if (value != null && !value.equals(found.getValue()))
      {
         setStatus(Status.FAILED, 
                   "For cookie '" + name + "' expected '" + value + "' but found '" + found.getValue() + "'");
         return;
      }
      
      setStatus(Status.PASSED, null);
      
      if (variable != null)
      {
         pool.createVariable(variable, found.getValue());
      }
   }

   /**
    * Parse all the response cookies in the <code>Set-cookie</code> headers and create a cookie store.
    * 
    * @param    headers
    *           The repsonse cookie headers.
    *           
    * @return   The cookie store.
    */
   private BasicCookieStore parseCookies(Header[] headers)
   {
      BasicCookieStore store = new BasicCookieStore();
      if (headers == null || headers.length == 0)
      {
         return store;
      }
      for (Header h : headers)
      {
         String header = h.getValue();
         List<HttpCookie> cookies = HttpCookie.parse(header);
         for (HttpCookie hc : cookies)
         {
            store.addCookie(new BasicClientCookie(hc.getName(), hc.getValue()));
         }
      }
      return store;
   }
}
