text: "use strict";
  
  import React, { Component } from "react";
  import { StyleSheet, TouchableWithoutFeedback, Platform, StatusBar, Animated, Image, Text, View,Dimensions } from "react-native";
  import { isIphoneX } from "react-native-iphone-x-helper";
  import PropTypes from "prop-types";
  
  import FlashMessageManager from "./FlashMessageManager";
  import FlashMessageWrapper, { styleWithInset } from "./FlashMessageWrapper";
  
  /**
   * MessageComponent `minHeight` property used mainly in vertical transitions
   */
  const OFFSET_HEIGHT = Platform.OS !== "ios" ? 60 : 48;
  
  /**
   * `message` prop it's expected to be some "object"
   * The `message` attribute is mandatory.
   * If you pass some `description` attribute your flash message will be displayed in two lines (first `message` as a title and after `description` as simple text)
   * The `type` attribute set the type and color of your flash message, default options are "success" (green), "warning" (orange), "danger" (red), "info" (blue) and "default" (gray)
   * If you need to customize the bg color or text color for a single message you can use the `backgroundColor` and `color` attributes
   */
  const MessagePropType = PropTypes.shape({
    message: PropTypes.string.isRequired,
    description: PropTypes.string,
    type: PropTypes.string,
    backgroundColor: PropTypes.string,
    color: PropTypes.string,
  }).isRequired;
  
  /**
   * Non-operation func
   */
  const noop = () => {};
  
  /**
   * Simple random ID for internal FlashMessage component usage
   */
  function srid() {
    function s4() {
      return Math.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1);
    }
  
    return `${s4()}-${s4()}-${s4()}`;
  }
  
  /**
   * Translates icon prop value into complex internal object
   */
  function parseIcon(icon = "none") {
    if (!!icon && icon !== "none") {
      if (typeof icon === "string") {
        return { icon, position: "left", style: {} };
      }
  
      return { position: "left", style: {}, ...icon };
    }
  
    return null;
  }
  
  /**
   * Translates string positions like "top", "bottom" and "center" to style classes
   */
  export function positionStyle(style, position) {
    if (typeof position === "string") {
      return [
        style,
        position === "top" && styles.rootTop,
        position === "bottom" && styles.rootBottom,
        position === "center" && styles.rootCenter,
      ];
    }
  
    return [style, position];
  }
  
  /**
   * Global function to handle show messages that can be called anywhere in your app
   * Pass some `message` object as first attribute to display flash messages in your app
   *
   * ```
   *  showMessage({ message: "Contact sent", description "Your message was sent with success", type: "success" })
   * ```
   */
  export function showMessage(...args) {
    const ref = FlashMessageManager.getDefault();
    if (!!ref) {
      ref.showMessage(...args);
    }
  }
  
  /**
   * Global function to programmatically hide messages that can be called anywhere in your app
   *
   * ```
   *  hideMessage()
   * ```
   */
  export function hideMessage(...args) {
    const ref = FlashMessageManager.getDefault();
    if (!!ref) {
      ref.hideMessage(...args);
    }
  }
  
  /**
   * Default transition config for FlashMessage component
   * You can create your own transition config with interpolation, just remember to return some style object with transform options
   */
  export function FlashMessageTransition(animValue, position = "top") {
    const opacity = animValue.interpolate({
      inputRange: [0, 1],
      outputRange: [0, 1],
    });
  
    if (position === "top") {
      const translateY = animValue.interpolate({
        inputRange: [0, 1],
        outputRange: [-OFFSET_HEIGHT, isIphoneX() ? 40 : 20],
      });
  
      return {
        transform: [{ translateY }],
        opacity,
      };
    } else if (position === "bottom") {
      const translateY = animValue.interpolate({
        inputRange: [0, 1],
        outputRange: [OFFSET_HEIGHT, 0],
      });
  
      return {
        transform: [{ translateY }],
        opacity,
      };
    }
  
    return {
      opacity,
    };
  }
  
  export const renderFlashMessageIcon = (icon = "success", style = {}, customProps = {}) => {
    switch (icon) {
      case "success":
        return (
          <Image style={[styles.flashIcon, style]} source={require("./icons/fm_icon_success.png")} {...customProps} />
        );
      case "info":
        return <Image style={[styles.flashIcon, style]} source={require("./icons/fm_icon_info.png")} {...customProps} />;
      case "warning":
        return (
          <Image style={[styles.flashIcon, style]} source={require("./icons/fm_icon_warning.png")} {...customProps} />
        );
      case "danger":
        return (
          <Image style={[styles.flashIcon, style]} source={require("./icons/fm_icon_danger.png")} {...customProps} />
        );
      default:
        return null;
    }
  };
  
  /**
   * Default MessageComponent used in FlashMessage
   * This component it's wrapped in `FlashMessageWrapper` to handle orientation change and extra inset padding in special devices
   * For most of uses this component doesn't need to be change for custom versions, cause it's very customizable
   */
  export const DefaultFlash = ({
    message,
    style,
    textStyle,
    titleStyle,
    renderFlashMessageIcon,
    position = "top",
    floating = false,
    icon,
    hideStatusBar = false,
    hideProgressBar = false,
    customContent,
    ...props
  }) => {
    const hasDescription = !!message.description && message.description !== "";
    const iconView =
      !!icon &&
      !!icon.icon &&
      renderFlashMessageIcon(icon.icon === "auto" ? message.type : icon.icon, [
        icon.position === "left" && styles.flashIconLeft,
        icon.position === "right" && styles.flashIconRight,
        icon.style,
      ]);
    const hasIcon = !!iconView;
  
    
  
    return (
      <FlashMessageWrapper position={typeof position === "string" ? position : null}>
        {wrapperInset => (
          <View
            style={styleWithInset(
              [
                styles.defaultFlash,
                position === "center" && styles.defaultFlashCenter,
                position !== "center" && floating && styles.defaultFlashFloating,
                hasIcon && styles.defaultFlashWithIcon,
                !!message.backgroundColor
                  ? { backgroundColor: message.backgroundColor }
                  : !!message.type &&
                    !!FlashMessage.ColorTheme[message.type] && {
                      backgroundColor: FlashMessage.ColorTheme[message.type],
                    },
                style,
              ],
              wrapperInset,
              !!hideStatusBar,
              position !== "center" && floating ? "margin" : "padding"
            )}
            {...props}>
            {hasIcon && icon.position === "left" && iconView}
            {message.customContent ? message.customContent : <View style={styles.flashLabel}>
              <Text
                style={[
                  styles.flashText,
                  hasDescription && styles.flashTitle,
                  !!message.color && { color: message.color },
                  titleStyle,
                ]}>
                {message.message}
              </Text>
              {hasDescription && (
                <Text style={[styles.flashText, !!message.color && { color: message.color }, textStyle]}>
                  {message.description}
                </Text>
              )}
            </View>}
            {hasIcon && icon.position === "right" && iconView}
          </View>
        )}
      </FlashMessageWrapper>
    );
  };
  
  DefaultFlash.propTypes = {
    message: MessagePropType,
    renderFlashMessageIcon: PropTypes.func,
  };
  
  /**
   * Main component of this package
   * The FlashMessage component it's a global utility to help you with easily and highly customizable flashbars, top notifications or alerts (with iPhone X "notch" support)
   * You can instace and use this component once in your main app screen
   * To global use, please add your <FlasshMessage /> as a last component in your root main screen
   *
   * ```
   *   <View style={{ flex: 1 }}>
   *     <YourMainApp />
   *     <FlasshMessage />   <--- here as last component
   *   <View>
   * ```
   */
  export default class FlashMessage extends Component {
    static defaultProps = {
      /**
       * Use to handle if the instance can be registed as default/global instance
       */
      canRegisterAsDefault: true,
      /**
       * Controls if the flash message can be closed on press
       */
      hideOnPress: true,
      /**
       * `onPress` callback for flash message press
       */
      onPress: noop,
      /**
       * Controls if the flash message will be shown with animation or not
       */
      animated: true,
      /**
       * Animations duration/speed
       */
      animationDuration: 225,
      /**
       * Controls if the flash message can hide itself after some `duration` time
       */
      autoHide: true,
      /**
       * How many milliseconds the flash message will be shown if the `autoHide` it's true
       */
      duration: 1850,
      /**
       * Controls if the flash message will auto hide the native status bar
       * Note: Works OK in iOS, not all Android versions support this.
       */
      hideStatusBar: false,
      /**
       * Controls if the progress bar is visible or not
       */
      hideProgressBar: false,
      /**
       * The `floating` prop unstick the message from the edges and applying some border radius to component
       */
      floating: false,
      /**
       * The `position` prop set the position of a flash message
       * Expected options: "top" (default), "bottom", "center" or a custom object with { top, left, right, bottom } position
       */
      position: "top",
      /**
       * The `icon` prop set the graphical icon of a flash message
       * Expected options: "none" (default), "auto" (guided by `type`), "success", "info", "warning", "danger" or a custom object with icon type/name and position (left or right) attributes, e.g.: { icon: "success", position: "right" }
       */
      icon: "none",
      /**
       * The `renderFlashMessageIcon` prop set a custom render function for inside message icons
       */
      renderFlashMessageIcon,
      /**
       * The `transitionConfig` prop set the transition config function used in shown/hide anim interpolations
       */
      transitionConfig: FlashMessageTransition,
      /**
       * The `MessageComponent` prop set the default flash message render component used to show all the messages
       */
      MessageComponent: DefaultFlash
    };
    static propTypes = {
      canRegisterAsDefault: PropTypes.bool,
      hideOnPress: PropTypes.bool,
      onShow: PropTypes.func,
      onHide: PropTypes.func,
      onPress: PropTypes.func,
      animated: PropTypes.bool,
      animationDuration: PropTypes.number,
      duration: PropTypes.number,
      autoHide: PropTypes.bool,
      hideStatusBar: PropTypes.bool,
      hideProgressBar: PropTypes.bool,
      floating: PropTypes.bool,
      position: PropTypes.oneOfType([PropTypes.string, PropTypes.array, PropTypes.object]),
      icon: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
      renderFlashMessageIcon: PropTypes.func,
      transitionConfig: PropTypes.func,
      MessageComponent: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
    };
    /**
     * Your can customize the default ColorTheme of this component
     * Use `setColorTheme` static method to override the primary colors/types of flash messages
     */
    static ColorTheme = {
      success: "#5cb85c",
      info: "#5bc0de",
      warning: "#f0ad4e",
      danger: "#d9534f",
    };
    static setColorTheme = theme => {
      FlashMessage.ColorTheme = Object.assign(FlashMessage.ColorTheme, theme);
    };
    constructor(props) {
      super(props);
  
      this.prop = this.prop.bind(this);
      this.pressMessage = this.pressMessage.bind(this);
      this.toggleVisibility = this.toggleVisibility.bind(this);
      if (!this._id) this._id = srid();
  
      this.state = {
        visibleValue: new Animated.Value(0),
        isHidding: false,
        message: props.message || null,
        bannerProgressValue: new Animated.Value(0)
      };
    }
    componentDidMount() {
      if (this.props.canRegisterAsDefault) {
        this.setState({ bannerProgressValue: new Animated.Value(0)});
        FlashMessageManager.register(this);
      }
    }
    componentWillUnmount() {
      if (this.props.canRegisterAsDefault) {
        FlashMessageManager.unregister(this);
      }
    }
    /**
     * Non-public method
     */
    prop(message, prop) {
      return !!message && prop in message ? message[prop] : prop in this.props ? this.props[prop] : null;
    }
    /**
     * Non-public method
     */
    isAnimated(message) {
      return this.prop(message, "animated");
    }
    /**
     * Non-public method
     */
    pressMessage(event) {
      if (!this.state.isHidding) {
        const { message } = this.state;
        const hideOnPress = this.prop(message, "hideOnPress");
        const onPress = this.prop(message, "onPress");
  
        if (hideOnPress) {
          this.hideMessage();
        }
  
        if (typeof onPress === "function") {
          onPress(event, message);
        }
      }
    }
    /**
     * Non-public method
     */
    toggleVisibility(visible = true, animated = true, done) {
      const { message } = this.state;
  
      const position = this.prop(message, "position");
      const animationDuration = this.prop(message, "animationDuration");
      const duration = this.prop(message, "duration");
      const autoHide = this.prop(message, "autoHide");
      const hideStatusBar = this.prop(message, "hideStatusBar");
  
  
  
      
      if (this._hideTimeout) {
        clearTimeout(this._hideTimeout);
  
      }
  
      if (visible) {
  
        const onShow = this.prop(message, "onShow") || noop;
        const finish = () => {
          if (!!autoHide && duration > 0) {
  
            this._hideTimeout = setTimeout(() => {this.toggleVisibility(false, animated);}, duration);
          }
  
          if (!!done && typeof done === "function") {
            done();
          }
        };
  
        this.setState({ isHidding: false });
        this.state.visibleValue.setValue(0);
        this.bannerProgressStart();
          
          
  
        if (!!onShow && typeof onShow === "function") {
          onShow(this);
        }
  
        if (!!hideStatusBar) {
          StatusBar.setHidden(true, typeof hideStatusBar === "string" ? hideStatusBar : "slide");
        }
  
        if (animated) {
          Animated.timing(this.state.visibleValue, {
            toValue: 1,
            duration: animationDuration,
            useNativeDriver: true,
          }).start(finish);
        } else {
          finish();
        }
      } else {
        const onHide = this.prop(message, "onHide") || noop;
        const finish = () => {
          this.setState({ message: null, isHidding: false });
  
          if (!!onHide && typeof onHide === "function") {
            onHide(this);
          }
  
          if (!!done && typeof done === "function") {
            done();
          }
        };
  
        this.setState({ isHidding: true });
        this.bannerProgressHide();
        
  
        if (!!hideStatusBar) {
          StatusBar.setHidden(false, typeof hideStatusBar === "string" ? hideStatusBar : "slide");
        }
  
        if (animated) {
          Animated.timing(this.state.visibleValue, {
            toValue: 0,
            duration: animationDuration,
            useNativeDriver: true,
          }).start(finish);
        } else {
          finish();
        }
      }
    }
    /**
     * Instace ref function to handle show messages
     * Pass some `message` object as first attribute to display a flash message
     *
     * ```
     * this.refs.YOUR_REF.showMessage({ message: "Contact sent", description "Your message was sent with success", type: "success" })
     * ```
     */
    showMessage(message, description = null, type = "default") {
      if (!!message) {
        let _message = {};
        if (typeof message === "string") {
          _message = { message, description, type };
        } else if ("message" in message) {
          _message = { description: null, type: "default", ...message };
        }
  
        const animated = this.isAnimated(_message);
        this.setState({ message: _message }, () => this.toggleVisibility(true, animated));
        return;
      }
  
  
      this.setState({ message: null, isHidding: false });
    }
    /**
     * Instace ref function to programmatically hide message
     *
     * ```
     * this.refs.YOUR_REF.hideMessage()
     * ```
     */
    hideMessage() {
      const animated = this.isAnimated(this.state.message);
  
      this.setState({ bannerProgressValue: new Animated.Value(10)});
      this.toggleVisibility(false, animated);
    }
  
    bannerProgressStart() {
      this.state.bannerProgressValue.setValue(0);
      Animated.timing(this.state.bannerProgressValue, {
        toValue: 10,
        duration: 10000,
        useNativeDriver:true
      }).start(() => {
      });
    }
  
    bannerProgressHide(message) {
      
    }
    render() {
      const { renderFlashMessageIcon, MessageComponent } = this.props;
      const { message, visibleValue, bannerProgressValue } = this.state;
  
      const style = this.prop(message, "style");
      const textStyle = this.prop(message, "textStyle");
      const titleStyle = this.prop(message, "titleStyle");
      const floating = this.prop(message, "floating");
      const position = this.prop(message, "position");
      const icon = parseIcon(this.prop(message, "icon"));
      const hideStatusBar = this.prop(message, "hideStatusBar");
      const hideProgressBar = this.prop(message, "hideProgressBar");
      const transitionConfig = this.prop(message, "transitionConfig");
      const animated = this.isAnimated(message);
      const animStyle = animated ? transitionConfig(visibleValue, position) : {};
      
  
      return (
        <Animated.View
          style={[
            positionStyle(styles.root, position),
            position === "center" && !!message && styles.rootCenterEnabled,
            animStyle,
          ]}>
          {!!message && (
            <TouchableWithoutFeedback onPress={this.pressMessage}>
              <MessageComponent
                position={position}
                floating={floating}
                message={message}
                hideStatusBar={hideStatusBar}
                renderFlashMessageIcon={renderFlashMessageIcon}
                icon={icon}
                style={style}
                textStyle={textStyle}
                titleStyle={titleStyle}
              />
            </TouchableWithoutFeedback>
          )}
          {hideProgressBar ? null : <View style={{width:Dimensions.get('window').width-32,overflow:"hidden"}}>
          <Animated.View
                  style={{
                    borderBottomColor: message ? message.color : 'white',
                    borderBottomWidth: 2,
                    borderRadius: 10,
                    width:Dimensions.get('window').width-32,
                    transform: [
                      {
                        translateX: bannerProgressValue.interpolate({
                          inputRange: [0, 12],
                          outputRange: [0,-Dimensions.get('window').width-32],
                        }),
                      }]
                  }}
                />
                </View>}
        </Animated.View>
      );
    }
    _hideTimeout;
    _id;
  }
  
  const styles = StyleSheet.create({
    root: {
      position: "absolute",
      left: 16,
      right: 16,
      borderRadius: 8,
      backgroundColor: "white",
      shadowColor: "rgba(0, 0, 0, 0.08)",
      shadowOffset: {
        width: 0,
        height: 16
      },
      shadowRadius: 24,
      shadowOpacity: 1,
    },
    rootTop: {
      top: 0,
    },
    rootBottom: {
      bottom: 0,
    },
    rootCenter: {
      
    },
    rootCenterEnabled: {
      top: 0,
      bottom: 0,
      width: "100%",
      height: "100%",
    },
    defaultFlash: {
      borderRadius:8,
      backgroundColor: "#696969",
    },
    defaultFlashCenter: {
      margin: 44,
      borderRadius: 8,
      overflow: "hidden",
    },
    defaultFlashFloating: {
      marginTop: 10,
      marginLeft: 12,
      marginRight: 12,
      borderRadius: 8,
    },
    defaultFlashWithIcon: {
      flexDirection: "row",
    },
    flashLabel: {
      flexDirection: "column",
    },
    flashText: {
      fontSize: 14,
      lineHeight: 18,
      color: "#fff",
    },
    flashTitle: {
      fontSize: 16,
      fontWeight: "600",
      marginBottom: 5,
    },
    flashIcon: {
      tintColor: "#fff",
      marginTop: -1,
      width: 21,
      height: 21,
    },
    flashIconLeft: {
      marginLeft: -6,
      marginRight: 9,
    },
    flashIconRight: {
      marginRight: -6,
      marginLeft: 9,
    },
  });
  