/*
 * Copyright 2010 Google Inc.
 *
 * 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
 *
 *      http://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.
 */
// Author: jmaessen@google.com (Jan Maessen)

#include "net/instaweb/rewriter/public/javascript_library_identification.h"

#include <utility>
#include <map>

#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/md5_hasher.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/http/google_url.h"

namespace net_instaweb {

const int JavascriptLibraryIdentification::kNumHashChars;

JavascriptLibraryIdentification::~JavascriptLibraryIdentification() { }

bool JavascriptLibraryIdentification::RegisterLibrary(
    SizeInBytes bytes, StringPiece md5_hash, StringPiece canonical_url) {
  // Validate the md5_hash and make sure canonical_url is vaguely sensible.
  for (StringPiece::const_iterator c = md5_hash.begin(),
           end = md5_hash.end(); c != end; ++c) {
    if (!(('a' <= *c && *c <= 'z') || ('A' <= *c && *c <= 'Z') ||
          ('0' <= *c && *c <= '9') || (*c == '-') || (*c == '_'))) {
      return false;
    }
  }
  // Check url for basic validity by resolving it against example.com.
  GoogleUrl base("http://www.example.com/");
  GoogleUrl gurl(base, canonical_url);
  if (!gurl.IsWebValid()) {
    return false;
  }
  MD5ToUrlMap& bytes_entry = libraries_[bytes];  // Creates inner map if absent.
  GoogleString md5_hash_string;
  md5_hash.CopyToString(&md5_hash_string);
  GoogleString& url_string = bytes_entry[md5_hash_string];
  // New entry overrides any previous entry.
  canonical_url.CopyToString(&url_string);
  return true;
}

StringPiece JavascriptLibraryIdentification::Find(
    StringPiece minified_code) const {
  // NOTE: we are careful to avoid content hashing here unless the code size
  // suggests a possible match.
  uint64 bytes = minified_code.size();
  LibraryMap::const_iterator bytes_entry = libraries_.find(bytes);
  if (bytes_entry != libraries_.end()) {
    // Size match found, compute the hash and look up against all
    // appropriately-sized entries.
    MD5Hasher hasher(kNumHashChars);
    GoogleString hash = hasher.Hash(minified_code);
    const MD5ToUrlMap& md5_map = bytes_entry->second;
    MD5ToUrlMap::const_iterator url_entry = md5_map.find(hash);
    if (url_entry != md5_map.end()) {
      return StringPiece(url_entry->second);
    }
  }
  // No size match found or no hash matched
  return StringPiece(NULL);
}

void JavascriptLibraryIdentification::Merge(
    const JavascriptLibraryIdentification& src) {
  for (LibraryMap::const_iterator bytes_entry = src.libraries_.begin(),
           bytes_end = src.libraries_.end();
       bytes_entry != bytes_end; ++bytes_entry) {
    const MD5ToUrlMap& src_md5_map = bytes_entry->second;
    MD5ToUrlMap& this_md5_map = libraries_[bytes_entry->first];
    for (MD5ToUrlMap::const_iterator md5_entry = src_md5_map.begin(),
             md5_end = src_md5_map.end();
         md5_entry != md5_end; ++md5_entry) {
      // Prefer entry in src.
      this_md5_map[md5_entry->first] = md5_entry->second;
    }
  }
}

void JavascriptLibraryIdentification::AppendSignature(
    GoogleString* signature) const {
  for (LibraryMap::const_iterator bytes_entry = libraries_.begin(),
           bytes_end = libraries_.end();
       bytes_entry != bytes_end; ++bytes_entry) {
    StrAppend(signature, "S:", Integer64ToString(bytes_entry->first));
    const MD5ToUrlMap& md5_map = bytes_entry->second;
    for (MD5ToUrlMap::const_iterator md5_entry = md5_map.begin(),
             md5_end = md5_map.end();
         md5_entry != md5_end; ++md5_entry) {
      StrAppend(signature, "_H:", md5_entry->first,
                "_J:", md5_entry->second);
    }
  }
}

}  // namespace net_instaweb
