/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */

#ifndef COBALT_CSSOM_MEDIA_FEATURE_KEYWORD_VALUE_H_
#define COBALT_CSSOM_MEDIA_FEATURE_KEYWORD_VALUE_H_

#include <string>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "cobalt/base/polymorphic_equatable.h"
#include "cobalt/cssom/property_value.h"

namespace cobalt {
namespace cssom {

class PropertyValueVisitor;

class MediaFeatureKeywordValue : public PropertyValue {
 public:
  enum Value {
    // "interlace" is a value of the "scan" media feature which indicates that
    // the display is interlaced.
    //   https://www.w3.org/TR/css3-mediaqueries/#scan
    kInterlace,

    // "landscape" is a value of the "orientation" media feature which indicates
    // that the display is oriented in landscape mode.
    //   https://www.w3.org/TR/css3-mediaqueries/#orientation
    kLandscape,

    // "portrait" is a value of the "orientation" media feature which indicates
    // that the display is oriented in portrait mode.
    //   https://www.w3.org/TR/css3-mediaqueries/#orientation
    kPortrait,

    // "progressive" is a value of the "scan" media feature which indicates that
    // the display is progressive (not interlaced).
    //   https://www.w3.org/TR/css3-mediaqueries/#scan
    kProgressive,
  };

  // Since keyword values do not hold additional information and some of them
  // (namely "inherit" and "initial") are used extensively, for the sake of
  // saving memory an explicit instantiation of this class is disallowed.
  // Use factory methods below to obtain shared instances.
  static const scoped_refptr<MediaFeatureKeywordValue>& GetInterlace();
  static const scoped_refptr<MediaFeatureKeywordValue>& GetLandscape();
  static const scoped_refptr<MediaFeatureKeywordValue>& GetPortrait();
  static const scoped_refptr<MediaFeatureKeywordValue>& GetProgressive();

  void Accept(PropertyValueVisitor* visitor) OVERRIDE;

  Value value() const { return value_; }

  std::string ToString() const OVERRIDE;
  bool operator==(const MediaFeatureKeywordValue& other) const {
    return value_ == other.value_;
  }

  DEFINE_POLYMORPHIC_EQUATABLE_TYPE(MediaFeatureKeywordValue);

  // Implementation detail, has to be public in order to be constructible.
  struct NonTrivialStaticFields;

 private:
  explicit MediaFeatureKeywordValue(Value value) : value_(value) {}
  ~MediaFeatureKeywordValue() OVERRIDE {}

  const Value value_;

  DISALLOW_COPY_AND_ASSIGN(MediaFeatureKeywordValue);
};

}  // namespace cssom
}  // namespace cobalt

#endif  // COBALT_CSSOM_MEDIA_FEATURE_KEYWORD_VALUE_H_
