/// <summary>
		/// Document: http://dev.twitter.com/doc/post/favorites/create/:id
		/// Supported formats: json, xml
		/// Supported request methods: POST
		/// Requires Authentication: true
		/// Rate Limited: false
		/// Required Parameters: id
		/// </summary>
		/// <param name="extension">xmlに対応</param>
		/// <param name="options">Documentを参照してください</param>
		/// <returns></returns>
		public static Status Create(Format extension, string id, params string[] options) {
			string query = TwitterUtility.GetQuery(ApiSelector.FavoritesCreate, extension, options);
			query = query.Replace("id.", id + ".");
			string response = ConfigurationViewModel.OAuth.oAuthWebRequest(oAuthTwitter.Method.POST, query, ModelUtility.GetOption(options));

			Status status = null;
			switch (extension) {
				case Format.Xml:
					var xmlDoc = new XmlDocument();
					xmlDoc.LoadXml(response);
					XmlNode node = xmlDoc.SelectSingleNode("/status");
					status = new Status(node, UserType.Others);
					break;
				case Format.Json:
				default:
					throw new NotImplementedException();
			}
			return status;
		}
		/// <summary>
		/// Document: http://dev.twitter.com/doc/get/statuses/show/:id
		/// Supported formats: json, xml
		/// Supported request methods: GET
		/// Requires Authentication: false
		/// Rate Limited: true
		/// Required Parameters: id
		/// </summary>
		/// <param name="extension">xmlに対応</param>
		/// <param name="options">Documentを参照してください</param>
		/// <returns></returns>
		public static Status Show(Format extension, string id, params string[] options) {
			string postData = string.Empty;
			string query = TwitterUtility.GetQuery(oAuthTwitter.Method.GET, ref postData, ApiSelector.StatusesShow, extension, options);
			query = query.Replace("id.", id + ".");
			string response = ModelUtility.DownloadContext(query);

			Status status = null;
			switch (extension) {
				case Format.Xml:
					var xmlDoc = new XmlDocument();
					xmlDoc.LoadXml(response);
					XmlNode node = xmlDoc.SelectSingleNode("status");
					status = new Status(node, UserType.Others);
					break;
				case Format.Atom:
				case Format.Json:
				case Format.Rss:
				default:
					throw new NotImplementedException();
			}
			return status;
		}
		public void RefreshMASearch(bool isOR, Status status, params string[] options) {
			const string appid = "tQ4GsN6xg678mGX4kKDUToaS9MuMfGd98P5lQLC459EIHzc225hSthjWnhJjlZOX";

			Main.WorkerFactory((s, e) => {
				var list = new List<string>();

				var sb = new StringBuilder();
				foreach (StatusText t in status.TextParser.ParsedText) {
					if (t.Type == StatusTextType.Normal) {
						sb.Append(t.Text);
					} else if (t.Type == StatusTextType.Hashtag) {
						if (!list.Contains(t.Text)) {
							list.Add(t.Text);
						}
					}
				}
				ResultSet result = MAService.Parse(appid, sb.ToString(), "ma");
				foreach (Word word in result.MAResult.WordList) {
					if (word.Pos == "名詞" && word.Surface != "RT") {
						if (!list.Contains(word.Surface)) {
							list.Add(word.Surface);
						}
					}
				}


				var query = isOR ? Search.FormatQ(list.ToArray()) : Search.FormatQByAnd(list.ToArray());
				RefreshMASearch(true, query, options);
			}, true).RunWorkerAsync();
		}
		private void InsertTabItem(Status entry, ObservableCollection<TabItem> to, string tabName) {
			Dispatch.Method(() => {
				if (entry != null && (to == UserTabItems || to == QueryTabItems || to == TrendTabItems || to == BuzztterTabItems)) {
					var all = to[0].DataContext as OrderedHashSet<Status>;
					all.Insert(entry);
				}

				TabItem found = null;
				foreach (TabItem tabItem in to) {
					if (tabItem.Header.ToString() == tabName) {
						found = tabItem;
						break;
					}
				}

				OrderedHashSet<Status> statuses;
				if (found == null) {
					statuses = new OrderedHashSet<Status>(OrderPred);
					to.Add(new TabItem {
						Header = tabName,
						Content = new TwitterDataGrid(),
						DataContext = statuses,
					});
				} else {
					statuses = found.DataContext as OrderedHashSet<Status>;
				}
				if (entry != null && statuses != null) {
					statuses.Insert(entry);
				}
			});
		}
		public void Remove(Status status) {
			Timeline.Remove(status);
			Mentions.Remove(status);
			Favorites.Remove(status);
		}
		public void InsertToTimeline(Status status) {
			Timeline.Insert(status);
			InsertToMentions(status);
			InsertToFavorites(status);
		}
		public void InsertToFavorites(Status status) {
			if (status.Favorited) {
				Favorites.Insert(status);
			}
		}
		public void InsertToMentions(Status status) {
			string screenName = Properties.Settings.Default.ScreenName;
			if (!string.IsNullOrEmpty(screenName) && status.Text.StartsWith("@" + screenName)) {
				Mentions.Insert(status);
			}
		}
		/// <summary>
		/// Document: http://dev.twitter.com/doc/post/statuses/update
		/// Supported formats: xml, json
		/// Supported request methods: POST
		/// Requires Authentication: true
		/// Rate Limited: false
		/// Required Parameters: status
		/// </summary>
		/// <param name="extension"></param>
		/// <param name="tweet"></param>
		/// <param name="options"></param>
		/// <returns></returns>
		public static Status Update(Format extension, string tweet, params string[] options) {
			string postData = "status=" + tweet;
			string query = TwitterUtility.GetQuery(oAuthTwitter.Method.POST, ref postData, ApiSelector.StatusesUpdate, extension, options);
			string response = oAuthTwitter.WebRequest(oAuthTwitter.Method.POST, query, postData);

			Status status = null;
			switch (extension) {
				case Format.Xml:
					var xmlDoc = new XmlDocument();
					xmlDoc.LoadXml(response);
					XmlNode node = xmlDoc.SelectSingleNode("status");
					status = new Status(node, UserType.Others);
					break;
				case Format.Json:
				default:
					throw new NotImplementedException();
			}
			return status;
		}
		/// <summary>
		/// UserStreamsで取得したデータを各デリゲートに委譲します。(未実装部分多し)
		/// Document: http://dev.twitter.com/pages/user_streams_suggestions
		/// Supported formats: json
		/// Supported request methods: POST
		/// Requires Authentication: true
		/// Rate Limited: false
		/// Required Parameters:
		/// </summary>
		/// <param name="onAdded">追加デリゲート:Statusが生成されるときに発生します。</param>
		/// <param name="onDeleted">削除デリゲート:Statusが削除されるときに発生します。</param>
		/// <param name="condition">実行条件デリゲート:データを取得するときに発生します。</param>
		/// <param name="post">Twitter API Docを参照してください</param>
		public static void RunUserStreams(Action<Status> onAdded, Action<Status> onDeleted, Action<Status> onFavorited, Action<Status> onUnFavorited, Func<bool> condition, string option, List<string> friends) {
			if (request != null) {
				Stop();
				return;
			}

			string postData = option == null ? string.Empty : option;
			string query = TwitterUtility.GetQuery(oAuthTwitter.Method.POST, ref postData, ApiSelector.UserStreams, Format.Json, null);
			byte[] bpostData = Encoding.UTF8.GetBytes(postData);

			try {
				request = WebRequest.Create(query) as HttpWebRequest;
				request.ServicePoint.Expect100Continue = false;
				request.Method = "POST";
				request.ContentType = "application/x-www-form-urlencoded";
				request.ContentLength = bpostData.Length;
				using (Stream requestStream = request.GetRequestStream()) {
					requestStream.Write(bpostData, 0, bpostData.Length);
					using (var response = request.GetResponse() as HttpWebResponse)
					using (var stream = response.GetResponseStream())
					using (var reader = new StreamReader(stream)) {
						while (condition()) {
							string line = reader.ReadLine();
							if (line == null)
								break;
							if (line == "")
								continue;

							var serializer = new JavaScriptSerializer();
							var source = serializer.Deserialize<Dictionary<string, object>>(line);

							if (source.ContainsKey("text")) {
								onAdded(new Status(source, CreatedAtFormatType.Streaming));
							} else if (source.ContainsKey("delete")) {
								var a = source["delete"] as Dictionary<string, object>;
								var b = a["status"] as Dictionary<string, object>;
								onDeleted(new Status(b, CreatedAtFormatType.Streaming));
							} else if (source.ContainsKey("friends")) {
								var ids = source["friends"] as ArrayList;
								foreach (object id in ids) {
									string sid = id.ToString();
									if (sid != null) {
										friends.Add(sid);
									}
								}
							} else if (source.ContainsKey("event")) {
								string eventName = source["event"] as string;
								if (eventName == "favorite") {
									var status = source["target_object"] as Dictionary<string, object>;
									var entry = new Status(status, CreatedAtFormatType.Streaming);
									entry.Favorited = true;
									onFavorited(entry);
								} else if (eventName == "unfavorite") {
									var status = source["target_object"] as Dictionary<string, object>;
									var entry = new Status(status, CreatedAtFormatType.Streaming);
									entry.Favorited = false;
									onUnFavorited(entry);
								}
							} else {
								Console.WriteLine(line);
								Console.WriteLine(source);
							}
						}
					}
				}
			} finally {
				Stop();
			}
		}