importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js');

const leagueSports = {
  mlb: 'baseball',
  nba: 'basketball',
  nfl: 'football',
  mls: 'soccer',
  nhl: 'hockey'
};

const apiRegex = new RegExp('\/((?:stats)|(?:splits)|(?:gamelog)|(?:roster))');

console.log('in sw 1');

const isValid = (response) => {
	if (!response) return false;
	const expiration = response.headers.get('sw-expiration');
	return (!expiration || parseFloat(expiration) > new Date().getTime());
};

const cacheCustomResponse = async (request, response, cache, expiration, headers, body) => {
  headers = headers || new Headers(response.headers);
  headers.append('sw-expiration', expiration);
  console.log('caching', request, cache, headers);
  
  if (!body)
    body = await response.blob().then((body) => body);
  
  console.log('cacheCustomResponse', request.url || request, body);
  
  const cachedResponse = new Response(body, { status: response.status, statusText: response.statusText, headers: headers });
  cache.put(request, cachedResponse.clone());
  return cachedResponse;
};

const playerLookupHandler = async ({request, event}) => {
  console.log('lookup', request);
  return caches.open('player-lookup').then((cache) => {
    return cache.match(request).then((response) => {
      if (isValid(response)) {
    		return response;
    	}
    	
      return fetch(request.url)
    	.then(response => {
    	  return response.json()
      	.then(json => {
      	  let allAthletes = [];
      	  if (json.items && json.items.length) {
      	    let athleteObj = {athletes: [], otherAthletes: []};
      	    const subject = request.headers.subject;
      	    
      	    loopResults:
      	    for (let searchResult of json.items) {
          	  if (searchResult.title.includes('Stats, News, Bio | ESPN')) {
          	    const linkSplit = searchResult.link.split('/'),
                	    playerID = linkSplit[7];
                	  
                for (let athlete of athleteObj['athletes']) {
                  console.log('checkcopy', athlete.id, playerID);
                  if (athlete.id === playerID)
                    continue loopResults;
                }
                	    
          	    const playerLeague = linkSplit[3],
          	          playerSport = leagueSports[playerLeague],
          	          athleteKey = (!subject || subject === playerSport) ? 'athletes' : 'otherAthletes';
          	    
        	      athleteObj[athleteKey].push({
        	        name: searchResult.title.replace(' Stats, News, Bio | ESPN', ''),
        	        id: playerID,
        	        sport: playerSport,
        	        league: playerLeague
        	      });
          	  }
      	    }
      	    allAthletes = athleteObj.athletes.concat(athleteObj.otherAthletes);
      	  }
      	  //cache.put(event.request.url, JSON.stringify(allAthletes));
      	  
      	  const headers = new Headers(response.headers);
      	  
      	  if (allAthletes.length) {
        	  const body = JSON.stringify(allAthletes);
        	  let date = new Date();
        	  date.setMonth(date.getMonth()+3);
        	  const expiration = date.getTime();
            return cacheCustomResponse(request, response, cache, expiration, headers, body);
      	  }
      	  else {
      	    return new Response('[]', { status: response.status, statusText: response.statusText, headers: headers });
      	  }
      	});
    	});
    });
  });
}

const apiHandler = async ({url, request, event, params}) => {
  console.log('handling api', url.href);
  const action = apiRegex.exec(url.pathname);
        cacheName = 'player-' + (action ? action[1] : 'info');
  return caches.open(cacheName).then((cache) => {
    return cache.match(request).then((response) => {
      console.log('caught api request!', url.pathname);
      if (isValid(response)) {
        console.log('returning valid');
    		return response;
    	}
    	else if (url.pathname.includes('/schedule')) {
    	  return scheduleHandler({request, url});
    	}
	
      return fetch(event.request).then((response) => {
        const responseClone = response.clone();
        /*if (!!action && !url.search) {
          response.clone().json().then(data => {
            console.log('got fetched api', data);
            const qs = '?' + data.filters.map(({name, value}) => (name + '=' + value)).join('&');
            cache.put(request.url + qs, responseClone);
          });
        }
        else {*/
          cache.put(request.url, responseClone);
        //}
        console.log('returning refetched');
        return response;
      }).catch((err) => {
        console.error('apierr', err)
        return null;
      });
    });
  });
};

const scheduleHandler = async ({request, url}) => {
  return caches.open('schedules').then((scheduleCache) => {
    return scheduleCache.match(request).then((response) => {
      /*if (isValid(response)) {
    		return response;
    	}*/
    	
      return fetch(request.url).then((response) => {
  			return response.clone().json().then(data => {
          console.log('Success overview:', data, request);
          let expiration;
          
          for (let event of data.events) {
            if (!event.status)
              expiration = new Date(event.date).getTime();
          }
          console.log('got expiration', expiration);
          if (expiration) {
    			  const linkedCaches = ['stats', 'splits', 'gamelog'],
    			        splitURL = url.pathname.split('/'),
    			        sport = splitURL[5],
    			        league = splitURL[6],
    			        athleteID = request.headers.get('athleteID'),
    			        apiURL = 'https://site.web.api.espn.com/apis/common/v3/sports/' + sport + '/' + (sport === 'soccer' ? '' : league + '/') + 'athletes/' + athleteID + '/',
    			        seasonType = data.season.type.toString();
    			        
    			  for (let linkedCache of linkedCaches) {
    			    caches.open('player-' + linkedCache).then((cache) => {
    			      console.log('schedule lookup', 'player-' + linkedCache, apiURL + linkedCache);
      			    cache.matchAll(apiURL + linkedCache, {ignoreSearch: true}).then((responses) => {
      			      
                  for (let response of responses) {
                    response.clone().json().then(json => {
                      
                      if (linkedCache === 'stats') {
                        console.log('cache response stat', seasonType, json);
                        for (let filter of json.filters) {
                          if (filter.name === 'seasontype') {
                            if (filter.value === seasonType) {
                              console.log('updating stats' + linkedCache, expiration, response.url)
                              cacheCustomResponse(response.url, response, cache, expiration);
                            }
                            break;
                          }
                        }
                      }
                      else {
                        for (let filter of json.filters) {
                          if (filter.name === 'season') {
                            console.log('cache response season', linkedCache, filter.value, filter.options[0].value);
                            if (filter.value === filter.options[0].value) { // is latest season
                              // TODO: only update cache if latest season has already ended (or next season has yet to begin)
                              console.log('updating splits or gamelogs' + linkedCache, expiration, response.url)
                              cacheCustomResponse(response.url, response, cache, expiration);
                            }
                            break;
                          }
                        }
                      }
                    });
                  }
                });
    			    });
      			}
          }
            
    			return cacheCustomResponse(request, response, scheduleCache, expiration);
    				
  				/*
  				const headers = new Headers(copy.headers);
  				headers.append('sw-expiration', expiration);
  				
  				return copy.blob().then((body) => {
  					return cache.put(request, new Response(body, { status: copy.status, statusText: copy.statusText, headers: headers }));
  				});*/
    				
        });
  		  return response;
  		})
      .catch((error) => {
        console.error(url, 'Error:', error);
        return null;
      });
    });
  });
};


workbox.routing.registerRoute(new RegExp('/overview'), scheduleHandler);
workbox.routing.registerRoute(new RegExp('/(?:stats)|(?:splits)|(?:gamelog)'), apiHandler);




workbox.routing.registerRoute(
  new RegExp('^https:\/\/www\.googleapis\.com\/customsearch\/v1\\?key=AIzaSyCtY0Ysdb7hL1o3d2eIkNFKQfzh6vg9l08&cx=d452d0da4f98a9c81'),
  playerLookupHandler
);


workbox.routing.registerRoute(
  new RegExp('^https:\/\/www\.googleapis\.com\/customsearch\/v1\\?key=AIzaSyCtY0Ysdb7hL1o3d2eIkNFKQfzh6vg9l08&cx=d83a0f4958be12349'),
  new workbox.strategies.CacheFirst({
    cacheName: 'wallpaper-lookup',
    plugins: [
      new workbox.cacheableResponse.CacheableResponsePlugin({
        statuses: [0, 200],
      })
    ]
  })
);

workbox.routing.registerRoute(
  new RegExp('^https:\/\/site\.web\.api\.espn\.com\/apis\/'),
  apiHandler
);


workbox.routing.registerRoute(
  new RegExp('^https:\/\/a\.espncdn\.com'),
  new workbox.strategies.CacheFirst({
    cacheName: 'espn-images',
    plugins: [
      new workbox.cacheableResponse.CacheableResponsePlugin({
        statuses: [0, 200],
      })
    ]
  })
);

workbox.routing.registerRoute(
  new RegExp('^https:\/\/(?:wallpapercave)|(?:wallpaperaccess)\.com'),
  new workbox.strategies.CacheFirst({
    cacheName: 'wallpapers',
    plugins: [
      new workbox.cacheableResponse.CacheableResponsePlugin({
        statuses: [0, 200],
      })
    ]
  })
);
