/** Created by Ishmael on 11/18/2015. */
public class WatchBotServer {
  private static final ApplicationContext context =
      new ClassPathXmlApplicationContext("app-config.xml");
  static Logger log = Logger.getLogger(WatchBotServer.class);

  public static void main(String[] args) {

    Twitter twitter = new TwitterFactory().getInstance();
    TwitterStream twitterStream = new TwitterStreamFactory().getInstance();
    MessageListener messageListener = null;
    Thread alertsWatcher = null;
    try {
      messageListener = new MessageListener(twitter, context);
      twitterStream.addListener(messageListener);
      twitterStream.user();
      alertsWatcher = new Thread(new AlertsWatcher(twitter, 15000));
      alertsWatcher.start();
    } catch (TwitterException e) {
      e.printStackTrace();
    }
  }

  private static void startup() {
    log.info("Starting up server");
  }

  private static void shutdown() {
    log.info("Shutting Down");
  }
}
// @Startup
@Singleton
public class TwitterStreamer {

  Logger logger = Logger.getLogger(TwitterStreamer.class);

  @Inject Event<Tweet> statusEvent;

  private void fireStatusEvent(Tweet tweet) {
    logger.info("Firing statusEvent from " + tweet.getAuthor());
    statusEvent.fire(tweet);
  }

  /**
   * This is where the automagic happens We are listening on tweets through the streaming api,
   * whenever we get a tweet "fireStatusEvent" is called
   */
  @PostConstruct
  public void startTweetStream() {
    TwitterStream twitterStream =
        new TwitterStreamFactory(TwitterConfigBuilder.getConfig()).getInstance();

    StatusListener statusListener =
        new StatusListener() {
          @Override
          public void onStatus(Status status) {
            logger.info("Received a status from " + status.getUser().getScreenName());
            Tweet tweet = new Tweet(status);
            fireStatusEvent(tweet);
          }

          @Override
          public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {}

          @Override
          public void onTrackLimitationNotice(int i) {}

          @Override
          public void onScrubGeo(long l, long l1) {}

          @Override
          public void onStallWarning(StallWarning stallWarning) {}

          @Override
          public void onException(Exception e) {
            e.printStackTrace();
          }
        };

    FilterQuery filter = new FilterQuery();
    String[] keywords = {"#testtestWOW"};
    filter.track(keywords);

    twitterStream.addListener(statusListener);
    twitterStream.filter(filter);
    logger.warn("Started to listen for " + keywords[0]);
  }
}
  /**
   * This is where the automagic happens We are listening on tweets through the streaming api,
   * whenever we get a tweet "fireStatusEvent" is called
   */
  @PostConstruct
  public void startTweetStream() {
    TwitterStream twitterStream =
        new TwitterStreamFactory(TwitterConfigBuilder.getConfig()).getInstance();

    StatusListener statusListener =
        new StatusListener() {
          @Override
          public void onStatus(Status status) {
            logger.info("Received a status from " + status.getUser().getScreenName());
            Tweet tweet = new Tweet(status);
            fireStatusEvent(tweet);
          }

          @Override
          public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {}

          @Override
          public void onTrackLimitationNotice(int i) {}

          @Override
          public void onScrubGeo(long l, long l1) {}

          @Override
          public void onStallWarning(StallWarning stallWarning) {}

          @Override
          public void onException(Exception e) {
            e.printStackTrace();
          }
        };

    FilterQuery filter = new FilterQuery();
    String[] keywords = {"#testtestWOW"};
    filter.track(keywords);

    twitterStream.addListener(statusListener);
    twitterStream.filter(filter);
    logger.warn("Started to listen for " + keywords[0]);
  }
 private static void shutdown() {
   log.info("Shutting Down");
 }
 private static void startup() {
   log.info("Starting up server");
 }
 private void fireStatusEvent(Tweet tweet) {
   logger.info("Firing statusEvent from " + tweet.getAuthor());
   statusEvent.fire(tweet);
 }
/**
 * @author Rémy Rakic - remy.rakic at gmail.com
 * @author Takao Nakaguchi - takao.nakaguchi at gmail.com
 * @author withgod - noname at withgod.jp
 * @since Twitter4J 2.1.8
 */
abstract class AbstractPhotoUploadImpl implements PhotoUpload {
  static final String TWITTER_VERIFY_CREDENTIALS_JSON_V1_1 =
      "https://api.twitter.com/1.1/account/verify_credentials.json";
  static final String TAG = "****";

  private HttpClient client;

  private Configuration conf = null;
  protected String apiKey = null;
  OAuthAuthorization oauth = null;
  String uploadUrl = null;
  HttpParameter[] postParameter = null;
  private HttpParameter[] appendParameter = null;
  String photo = null;
  HttpParameter message = null;
  final Map<String, String> headers = new HashMap<String, String>();
  HttpResponse httpResponse = null;
  private static final Logger logger = Logger.getLogger(AbstractPhotoUploadImpl.class);

  AbstractPhotoUploadImpl(Configuration conf, OAuthAuthorization oauth) {
    this.oauth = oauth;
    this.conf = conf;
    try {
    } catch (Exception e) {
      e.printStackTrace();
    }

    client = HttpClientFactory.getInstance(conf.getHttpClientConfiguration());
  }

  AbstractPhotoUploadImpl(Configuration conf, String apiKey, OAuthAuthorization oauth) {
    this(conf, oauth);
    this.apiKey = apiKey;
  }

  @Override
  public String upload(String photoFileName, InputStream photoBody) throws TwitterException {

    //        this.photo = new HttpParameter("media", photoFileName, photoBody);
    return upload();
  }

  @Override
  public String upload(String photoFileName, InputStream photoBody, String message)
      throws TwitterException {
    //        this.photo = new HttpParameter("media", photoFileName, photoBody);
    this.message = new HttpParameter("message", message);
    return upload();
  }

  @Override
  public String upload(File file, String message) throws TwitterException {
    this.photo = file.getAbsolutePath();
    this.message = new HttpParameter("message", message);
    return upload();
  }

  @Override
  public String upload(File file) throws TwitterException {
    this.photo = file.getAbsolutePath();
    return upload();
  }

  private String upload() throws TwitterException {

    if (conf.getMediaProviderParameters() != null && this.appendParameter.length > 0) {
      this.postParameter = appendHttpParameters(this.postParameter, this.appendParameter);
    }
    String media_id_string_init = post();
    return media_id_string_init;
  }

  private String post() {
    uploadUrl = "https://upload.twitter.com/1.1/media/upload.json";
    HttpParameter[] params = new HttpParameter[1];
    try {
      InputStream is = new FileInputStream(new File(this.photo));
      params[0] = new HttpParameter("media", photo, is);
      postParameter = params;
    } catch (Exception e) {
      e.printStackTrace();
    }
    headers.putAll(client.getRequestHeaders());
    HttpRequest req = new HttpRequest(RequestMethod.POST, uploadUrl, postParameter, null, headers);
    String authheader = oauth.getAuthorizationHeader(req);
    headers.put("Authorization", authheader);
    HttpRequest req2 = new HttpRequest(RequestMethod.POST, uploadUrl, postParameter, null, headers);
    try {
      httpResponse = client.request(req2, null);
      if (httpResponse.getStatusCode() != 202) {
        Log.e(
            "Error from Twitter",
            "get error in post:"
                + httpResponse.getStatusCode()
                + ", details:"
                + httpResponse.toString());
      }
      return httpResponse.asJSONObject().getString("media_id_string");
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  protected abstract void preUpload() throws TwitterException;

  protected abstract String postUpload() throws TwitterException;

  HttpParameter[] appendHttpParameters(HttpParameter[] src, HttpParameter[] dst) {
    int srcLen = src.length;
    int dstLen = dst.length;
    HttpParameter[] ret = new HttpParameter[srcLen + dstLen];
    System.arraycopy(src, 0, ret, 0, srcLen);
    System.arraycopy(dst, 0, ret, srcLen, dstLen);
    return ret;
  }

  String generateVerifyCredentialsAuthorizationHeader() {
    List<HttpParameter> oauthSignatureParams =
        oauth.generateOAuthSignatureHttpParams(
            "GET", AbstractPhotoUploadImpl.TWITTER_VERIFY_CREDENTIALS_JSON_V1_1);
    return "OAuth realm=\"https://api.twitter.com/\","
        + OAuthAuthorization.encodeParameters(oauthSignatureParams, ",", true);
  }

  protected String generateVerifyCredentialsAuthorizationURL(String verifyCredentialsUrl) {
    List<HttpParameter> oauthSignatureParams =
        oauth.generateOAuthSignatureHttpParams("GET", verifyCredentialsUrl);
    return verifyCredentialsUrl + "?" + OAuthAuthorization.encodeParameters(oauthSignatureParams);
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    AbstractPhotoUploadImpl that = (AbstractPhotoUploadImpl) o;

    if (apiKey != null ? !apiKey.equals(that.apiKey) : that.apiKey != null) return false;
    if (!Arrays.equals(appendParameter, that.appendParameter)) return false;
    if (client != null ? !client.equals(that.client) : that.client != null) return false;
    if (conf != null ? !conf.equals(that.conf) : that.conf != null) return false;
    if (headers != null ? !headers.equals(that.headers) : that.headers != null) return false;
    if (httpResponse != null ? !httpResponse.equals(that.httpResponse) : that.httpResponse != null)
      return false;
    if (photo != null ? !photo.equals(that.photo) : that.photo != null) return false;
    if (message != null ? !message.equals(that.message) : that.message != null) return false;
    if (oauth != null ? !oauth.equals(that.oauth) : that.oauth != null) return false;
    if (!Arrays.equals(postParameter, that.postParameter)) return false;
    if (uploadUrl != null ? !uploadUrl.equals(that.uploadUrl) : that.uploadUrl != null)
      return false;

    return true;
  }

  @Override
  public int hashCode() {
    int result = client != null ? client.hashCode() : 0;
    result = 31 * result + (conf != null ? conf.hashCode() : 0);
    result = 31 * result + (apiKey != null ? apiKey.hashCode() : 0);
    result = 31 * result + (oauth != null ? oauth.hashCode() : 0);
    result = 31 * result + (uploadUrl != null ? uploadUrl.hashCode() : 0);
    result = 31 * result + (postParameter != null ? Arrays.hashCode(postParameter) : 0);
    result = 31 * result + (appendParameter != null ? Arrays.hashCode(appendParameter) : 0);
    result = 31 * result + (photo != null ? photo.hashCode() : 0);
    result = 31 * result + (message != null ? message.hashCode() : 0);
    result = 31 * result + (headers != null ? headers.hashCode() : 0);
    result = 31 * result + (httpResponse != null ? httpResponse.hashCode() : 0);
    return result;
  }

  @Override
  public String toString() {
    return "AbstractPhotoUploadImpl{"
        + "client="
        + client
        + ", conf="
        + conf
        + ", apiKey='"
        + apiKey
        + '\''
        + ", oauth="
        + oauth
        + ", uploadUrl='"
        + uploadUrl
        + '\''
        + ", postParameter="
        + (postParameter == null ? null : Arrays.asList(postParameter))
        + ", appendParameter="
        + (appendParameter == null ? null : Arrays.asList(appendParameter))
        + ", photo="
        + photo
        + ", message="
        + message
        + ", headers="
        + headers
        + ", httpResponse="
        + httpResponse
        + '}';
  }
}