// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <AppKit/AppKit.h>

#include "base/memory/scoped_nsobject.h"
#include "base/memory/scoped_ptr.h"
#include "base/utf_string_conversions.h"
#import "content/common/mac/attributed_string_coder.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"

using mac::AttributedStringCoder;

class AttributedStringCoderTest : public testing::Test {
 public:
  NSMutableAttributedString* NewAttrString() {
    NSString* str = @"The quick brown fox jumped over the lazy dog.";
    return [[NSMutableAttributedString alloc] initWithString:str];
  }

  NSDictionary* FontAttribute(NSString* name, CGFloat size) {
    NSFont* font = [NSFont fontWithName:name size:size];
    return [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
  }

  NSAttributedString* EncodeAndDecode(NSAttributedString* str) {
    scoped_ptr<const AttributedStringCoder::EncodedString> encoded_str(
        AttributedStringCoder::Encode(str));
    return AttributedStringCoder::Decode(encoded_str.get());
  }
};

TEST_F(AttributedStringCoderTest, SimpleString) {
  scoped_nsobject<NSMutableAttributedString> attr_str(NewAttrString());
  [attr_str addAttributes:FontAttribute(@"Helvetica", 12.5)
                    range:NSMakeRange(0, [attr_str length])];

  NSAttributedString* decoded = EncodeAndDecode(attr_str.get());
  EXPECT_NSEQ(attr_str.get(), decoded);
}

TEST_F(AttributedStringCoderTest, NoAttributes) {
  scoped_nsobject<NSAttributedString> attr_str(NewAttrString());
  NSAttributedString* decoded = EncodeAndDecode(attr_str.get());
  EXPECT_NSEQ(attr_str.get(), decoded);
}

TEST_F(AttributedStringCoderTest, StripColor) {
  scoped_nsobject<NSMutableAttributedString> attr_str(NewAttrString());
  const NSUInteger kStringLength = [attr_str length];
  [attr_str addAttribute:NSFontAttributeName
                   value:[NSFont systemFontOfSize:26]
                   range:NSMakeRange(0, kStringLength)];
  [attr_str addAttribute:NSForegroundColorAttributeName
                   value:[NSColor redColor]
                   range:NSMakeRange(0, kStringLength)];

  NSAttributedString* decoded = EncodeAndDecode(attr_str.get());

  NSRange range;
  NSDictionary* attrs = [decoded attributesAtIndex:0 effectiveRange:&range];
  EXPECT_TRUE(NSEqualRanges(NSMakeRange(0, kStringLength), range));
  EXPECT_NSEQ([NSFont systemFontOfSize:26],
              [attrs objectForKey:NSFontAttributeName]);
  EXPECT_FALSE([attrs objectForKey:NSForegroundColorAttributeName]);
}

TEST_F(AttributedStringCoderTest, MultipleFonts) {
  scoped_nsobject<NSMutableAttributedString> attr_str(NewAttrString());
  [attr_str setAttributes:FontAttribute(@"Courier", 12)
                    range:NSMakeRange(0, 10)];
  [attr_str addAttributes:FontAttribute(@"Helvetica", 16)
                    range:NSMakeRange(12, 6)];
  [attr_str addAttributes:FontAttribute(@"Helvetica", 14)
                    range:NSMakeRange(15, 5)];

  NSAttributedString* decoded = EncodeAndDecode(attr_str);

  EXPECT_NSEQ(attr_str.get(), decoded);
}

TEST_F(AttributedStringCoderTest, NoPertinentAttributes) {
  scoped_nsobject<NSMutableAttributedString> attr_str(NewAttrString());
  [attr_str addAttribute:NSForegroundColorAttributeName
                   value:[NSColor blueColor]
                   range:NSMakeRange(0, 10)];
  [attr_str addAttribute:NSBackgroundColorAttributeName
                   value:[NSColor blueColor]
                   range:NSMakeRange(15, 5)];
  [attr_str addAttribute:NSKernAttributeName
                   value:[NSNumber numberWithFloat:2.6]
                   range:NSMakeRange(11, 3)];

  NSAttributedString* decoded = EncodeAndDecode(attr_str.get());

  scoped_nsobject<NSAttributedString> expected(NewAttrString());
  EXPECT_NSEQ(expected.get(), decoded);
}

TEST_F(AttributedStringCoderTest, NilString) {
  NSAttributedString* decoded = EncodeAndDecode(nil);
  EXPECT_TRUE(decoded);
  EXPECT_EQ(0U, [decoded length]);
}

TEST_F(AttributedStringCoderTest, OutOfRange) {
  AttributedStringCoder::EncodedString encoded(ASCIIToUTF16("Hello World"));
  encoded.attributes()->push_back(
      AttributedStringCoder::FontAttribute(
          FontDescriptor([NSFont systemFontOfSize:12]),
          ui::Range(0, 5)));
  encoded.attributes()->push_back(
      AttributedStringCoder::FontAttribute(
          FontDescriptor([NSFont systemFontOfSize:14]),
          ui::Range(5, 100)));
  encoded.attributes()->push_back(
      AttributedStringCoder::FontAttribute(
          FontDescriptor([NSFont systemFontOfSize:16]),
          ui::Range(100, 5)));

  NSAttributedString* decoded = AttributedStringCoder::Decode(&encoded);
  EXPECT_TRUE(decoded);

  NSRange range;
  NSDictionary* attrs = [decoded attributesAtIndex:0 effectiveRange:&range];
  EXPECT_NSEQ([NSFont systemFontOfSize:12],
              [attrs objectForKey:NSFontAttributeName]);
  EXPECT_TRUE(NSEqualRanges(range, NSMakeRange(0, 5)));

  attrs = [decoded attributesAtIndex:5 effectiveRange:&range];
  EXPECT_FALSE([attrs objectForKey:NSFontAttributeName]);
  EXPECT_EQ(0U, [attrs count]);
}
