/*
 * Copyright 2012 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: rahulbansal@google.com (Rahul Bansal)

#ifndef NET_INSTAWEB_REWRITER_PUBLIC_SPLIT_HTML_FILTER_H_
#define NET_INSTAWEB_REWRITER_PUBLIC_SPLIT_HTML_FILTER_H_

#include <vector>

#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/script_tag_scanner.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "net/instaweb/rewriter/public/suppress_prehead_filter.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/json.h"
#include "pagespeed/kernel/base/json_writer.h"
#include "pagespeed/kernel/base/null_writer.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"

namespace net_instaweb {

class HtmlElement;
class RewriteOptions;
class SplitHtmlConfig;
class SplitHtmlState;
class StaticAssetManager;
class Writer;

// Splits the incoming html content into above the fold html and below the
// fold json based on critical line specification stored in property cache.

// This filter will stream above the fold html and send below the fold json at
// EndDocument. It directly writes to the http request.
class SplitHtmlFilter : public SuppressPreheadFilter {
 public:
  static const char kSplitSuffixJsFormatString[];
  static const char kSplitTwoChunkSuffixJsFormatString[];
  static const char kLoadHiResImages[];
  static const char kMetaReferer[];

  explicit SplitHtmlFilter(RewriteDriver* rewrite_driver);
  virtual ~SplitHtmlFilter();

  virtual void DetermineEnabled(GoogleString* disabled_reason);

  virtual void StartDocument();
  virtual void EndDocument();

  virtual void StartElement(HtmlElement* element);
  virtual void EndElement(HtmlElement* element);

  static const GoogleString& GetBlinkJsUrl(
      const RewriteOptions* options,
      const StaticAssetManager* static_asset_manager);

  virtual const char* Name() const { return "SplitHtmlFilter"; }

 private:
  const SplitHtmlConfig* config() const {
    return driver()->split_html_config();
  }
  const StaticAssetManager* static_asset_manager() const {
    return driver()->server_context()->static_asset_manager();
  }

  void ServeNonCriticalPanelContents(const Json::Value& json);

  // Sets panel-id attribute to the element. This is not used by client-side
  // binding now.
  void MarkElementWithPanelId(HtmlElement* element,
                              const GoogleString& panel_id);

  // Reads the panel-id attribute and returns the value
  GoogleString GetPanelIdForInstance(HtmlElement* element);

  // Returns a string representation of the critical line config.
  GoogleString GenerateCriticalLineConfigString();

  // Pops the json from top of the stack and merges with parent panel which is
  // one below it.
  void EndPanelInstance();

  // Pushes new Json to the top of the stack corresponding to element.
  void StartPanelInstance(HtmlElement* element);

  // Inserts <!-- GooglePanel begin --> and <!-- GooglePanel end --> stubs.
  void InsertPanelStub(HtmlElement* element, const GoogleString& panel_id);

  // Appends dict to the dictionary array
  void AppendJsonData(Json::Value* dictionary, const Json::Value& dict);

  void WriteString(const StringPiece& str);

  // Inserts lazy load and other scripts needed for split initialization into
  // the head element. If no head tag in the page, it inserts one before
  // body tag.
  void InsertSplitInitScripts(HtmlElement* element);

  void InvokeBaseHtmlFilterStartDocument();

  void InvokeBaseHtmlFilterStartElement(HtmlElement* element);

  void InvokeBaseHtmlFilterEndElement(HtmlElement* element);

  void InvokeBaseHtmlFilterEndDocument();

  // Returns true, if the cross-origin is allowed by looking it up in
  // RewriteOptions::access_control_allow_origins()
  // Note: The cross-origin must match exactly inclusing the protocol.
  // The only wildcard supported is '*' which means allow all domains.
  bool IsAllowedCrossDomainRequest(StringPiece cross_origin);

  scoped_ptr<SplitHtmlState> state_;
  const RewriteOptions* options_;
  std::vector<ElementJsonPair> element_json_stack_;
  Json::FastWriter fast_writer_;
  scoped_ptr<JsonWriter> json_writer_;
  Writer* original_writer_;
  NullWriter null_writer_;
  StringPiece url_;
  bool script_written_;
  bool flush_head_enabled_;
  bool disable_filter_;
  bool inside_pagespeed_no_defer_script_;
  bool serve_response_in_two_chunks_;
  int last_script_index_before_panel_stub_;
  bool panel_seen_;
  ScriptTagScanner script_tag_scanner_;

  DISALLOW_COPY_AND_ASSIGN(SplitHtmlFilter);
};

}  // namespace net_instaweb

#endif  // NET_INSTAWEB_REWRITER_PUBLIC_SPLIT_HTML_FILTER_H_
